这道题关键是有两个延迟标记
当区间被完全覆盖时,要撤销抑或操作
所以每次先判断当前区间有没有被完全覆盖
有的话就直接改变相应的值,没有的话在判断有无异或标记
主要是这个地方要注意,其他地方都和另外一道题一样
代码有点长,但是不难
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 100010; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int num0[maxn<<2],num1[maxn<<2]; int lb0[maxn<<2],lb1[maxn<<2]; int rb0[maxn<<2],rb1[maxn<<2]; int mx1[maxn<<2],mx0[maxn<<2]; int col[maxn<<2]; int xor[maxn<<2]; int num; int max(int a,int b){ return a>b?a:b; } int min(int a,int b){ return a<b?a:b; } void pushup(int rt,int m) { lb0[rt]=lb0[rt<<1];rb0[rt]=rb0[rt<<1|1]; if(lb0[rt]==m-(m>>1)) lb0[rt]+=lb0[rt<<1|1]; if(rb0[rt]==(m>>1)) rb0[rt]+=rb0[rt<<1]; lb1[rt]=lb1[rt<<1];rb1[rt]=rb1[rt<<1|1]; if(lb1[rt]==m-(m>>1)) lb1[rt]+=lb1[rt<<1|1]; if(rb1[rt]==(m>>1)) rb1[rt]+=rb1[rt<<1]; num0[rt]=num0[rt<<1]+num0[rt<<1|1]; num1[rt]=num1[rt<<1]+num1[rt<<1|1]; mx1[rt]=max(mx1[rt<<1],mx1[rt<<1|1]); mx1[rt]=max(mx1[rt],rb1[rt<<1]+lb1[rt<<1|1]); mx0[rt]=max(mx0[rt<<1],mx0[rt<<1|1]); mx0[rt]=max(mx0[rt],rb0[rt<<1]+lb0[rt<<1|1]); } void build(int l,int r,int rt){ col[rt]=-1; xor[rt]=0; if(l==r){ scanf("%d",&num); num0[rt]=lb0[rt]=rb0[rt]=mx0[rt]=(num?0:1); num1[rt]=lb1[rt]=rb1[rt]=mx1[rt]=(num?1:0); return ; } int m=(l+r)>>1; build(lson); build(rson); pushup(rt,r-l+1); } void init(int rt,int m,int cmd){ lb0[rt]=rb0[rt]=mx0[rt]=num0[rt]=m*(1-cmd); lb1[rt]=rb1[rt]=mx1[rt]=num1[rt]=m*cmd; } void change(int rt){ swap(lb0[rt],lb1[rt]); swap(rb0[rt],rb1[rt]); swap(mx0[rt],mx1[rt]); swap(num0[rt],num1[rt]); } void pushdown(int rt,int m){ if(col[rt]!=-1){ col[rt<<1]=col[rt<<1|1]=col[rt]; xor[rt<<1]=xor[rt<<1|1]=0; init(rt<<1,m-(m>>1),col[rt]); init(rt<<1|1,(m>>1),col[rt]); col[rt]=-1; } else if(xor[rt]){ if(col[rt<<1]!=-1){ col[rt<<1]^=1; init(rt<<1,m-(m>>1),col[rt<<1]); } else { xor[rt<<1]^=1; change(rt<<1); } if(col[rt<<1|1]!=-1){ col[rt<<1|1]^=1; init(rt<<1|1,(m>>1),col[rt<<1|1]); } else { xor[rt<<1|1]^=1; change(rt<<1|1); } xor[rt]=0; } } void update(int L,int R,int cmd,int l,int r,int rt){ if(L<=l&&r<=R){ if(cmd<=1){ xor[rt]=0;//取消异或标记 col[rt]=cmd;//真个区间被完全覆盖为cmd init(rt,r-l+1,cmd); } else { if(col[rt]!=-1){//被完全覆盖,全是0或者全是1,相当于取反 col[rt]^=1; init(rt,r-l+1,col[rt]); } else { xor[rt]^=1; change(rt); } } return ; } pushdown(rt,r-l+1); int m=(l+r)>>1; if(L<=m) update(L,R,cmd,lson); if(R>m) update(L,R,cmd,rson); pushup(rt,r-l+1); } int query1(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R) return num1[rt]; pushdown(rt,r-l+1); int m=(l+r)>>1; int ans=0; if(L<=m) ans+=query1(L,R,lson); if(R>m) ans+=query1(L,R,rson); return ans; } int query2(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R) { return mx1[rt]; } pushdown(rt,r-l+1); int m=(l+r)>>1; if(R<=m) return query2(L,R,lson); if(L>m) return query2(L,R,rson); int a=query2(L,R,lson); int b=query2(L,R,rson); a=a>b?a:b; b=min(m-L+1,rb1[rt<<1])+min(R-m,lb1[rt<<1|1]); return a>b?a:b; } int main(){ int t,n,m,op,a,b; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); build(0,n-1,1); while(m--){ scanf("%d%d%d",&op,&a,&b); if(op<=2) update(a,b,op,0,n-1,1); else { if(op==3) printf("%d\n",query1(a,b,0,n-1,1)); else printf("%d\n",query2(a,b,0,n-1,1)); } } } return 0; }