把各种线段树的“基础”功能全都搞到一块了= =。。。
区间异或+覆盖,
连续01区间,
区间求和。。。。。
大体上没什么变化,不过pushdown的时候分成了覆盖操作和异或操作两种情况来更新连续区间的左连续和右连续。
代码中唯一不太好的地方就是tot是求和,sum是连续1的最长区间的值。。。
#include<stdio.h> #include<algorithm> #define ls rt*2 #define rs rt*2+1 #define lson l,mid,ls #define rson mid+1,r,rs #define canshu int l,int r,int rt #define X 400010 using namespace std; int ll,rr,c; int lzc[X],lzx[X],tot[X]; int lv[2][X],rv[2][X],sum[2][X]; void tset(canshu){ lv[l][rt]=rv[l][rt]=sum[l][rt]=r; } void Xor(int rt){ if(lzc[rt]!=-1)lzc[rt]^=1; else lzx[rt]^=1; } void change(int rt){ swap(lv[1][rt],lv[0][rt]); swap(rv[1][rt],rv[0][rt]); swap(sum[1][rt],sum[0][rt]); } void pushup(canshu){ int mid=l+r>>1; tot[rt]=tot[ls]+tot[rs]; for(int i=0;i<=1;i++){ lv[i][rt]=lv[i][ls]+(lv[i][ls]==mid-l+1?lv[i][rs]:0); rv[i][rt]=rv[i][rs]+(rv[i][rs]==r-mid ?rv[i][ls]:0); sum[i][rt]=max(max(sum[i][ls],sum[i][rs]),rv[i][ls]+lv[i][rs]); } } void pushdown(canshu){ int mid=l+r>>1; if(lzc[rt]!=-1){ lzc[ls]=lzc[rs]=lzc[rt]; lzx[ls]=lzx[rs]=0; tot[ls]=lzc[rt]*(mid-l+1); tot[rs]=lzc[rt]*(r-mid); tset(lzc[rt],mid-l+1,ls); tset(lzc[rt],r-mid,rs); tset(!lzc[rt],0,ls); tset(!lzc[rt],0,rs); lzc[rt]=-1;lzx[rt]=0; } if(lzx[rt]){ Xor(ls);Xor(rs); change(ls);change(rs); tot[ls]=mid-l+1-tot[ls]; tot[rs]=r-mid-tot[rs]; lzx[rt]=0; } } void build(canshu){ lzx[rt]=0;lzc[rt]=-1; if(l==r){ scanf("%d",&c); tot[rt]=c; tset(c,1,rt); tset(!c,0,rt); return ; } int mid=l+r>>1; build(lson); build(rson); pushup(l,r,rt); } void update(canshu){ if(ll<=l&&rr>=r){ if(c==-1){ Xor(rt); change(rt); tot[rt]=r-l+1-tot[rt]; } else{ tot[rt]=c*(r-l+1); tset(c,r-l+1,rt); tset(!c,0,rt); lzc[rt]=c;lzx[rt]=0; } return ; } pushdown(l,r,rt); int mid=l+r>>1; if(ll<=mid)update(lson); if(rr> mid)update(rson); pushup(l,r,rt); } int quesum(canshu){ if(ll<=l&&rr>=r)return sum[1][rt]; int mid=l+r>>1; pushdown(l,r,rt); if(rr<=mid)return quesum(lson); if(ll> mid)return quesum(rson); int tmp=min(rv[1][ls],mid-ll+1)+min(lv[1][rs],rr-mid); return max(max(quesum(lson),quesum(rson)),tmp); } int quetot(canshu){ if(ll<=l&&rr>=r)return tot[rt]; int mid=l+r>>1,as=0; pushdown(l,r,rt); if(ll<=mid)as=quetot(lson); if(rr>mid)as+=quetot(rson); return as; } int main(){ int cs,i,n,m; scanf("%d",&cs); while(cs--){ scanf("%d%d",&n,&m); n--; build(0,n,1); while(m--){ scanf("%d%d%d",&i,&ll,&rr); if(i<2){ c=i;update(0,n,1); } else if(i==2){c=-1;update(0,n,1);} else printf("%d\n",i==3?quetot(0,n,1):quesum(0,n,1)); } } return 0; }