1 10 10 0 0 0 1 1 0 1 0 1 1 1 0 2 3 0 5 2 2 2 4 0 4 0 3 6 2 3 7 4 2 8 1 0 5 0 5 6 3 3 9
5 2 65
这道题是前面线段树知识的综合题,也和之前有些不同,是个很好的训练题,做了很长时间啊,还需努力。这里的难点是异或运算,即把区间中的0变成1,1变成0.这里我维护每个区间的llen0,rlen0,tlen0,llen1,rlen1,tlen1,即区间从左端点起的向右最大连续0(1)区间长度,从右端起的最大向左连续0(1)区间长度,以及区间最大的连续0(1)区间长度,然后异或操作的时候,只要把0,1换一下,然后用pushup操作就可以了,再记录一个异或操作符x_or.
<pre name="code" class="cpp">#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<string> #include<algorithm> using namespace std; typedef long long ll; #define inf 0x7fffffff #define maxn 100050 int a[maxn]; struct node{ int l,r,yihuo,cnt; int llen0,rlen0,tlen0; int llen1,rlen1,tlen1; int num0,num1; }b[4*maxn]; int num1,num2; void pushdown(int i) { if(b[i].l==b[i].r)return; if(b[i].cnt!=-1){ b[i*2].cnt=b[i*2+1].cnt=b[i].cnt; b[i*2].yihuo=b[i*2+1].yihuo=0; if(b[i].cnt==0){ b[i*2].llen0=b[i*2].rlen0=b[i*2].tlen0=b[i*2].r-b[i*2].l+1; b[i*2].llen1=b[i*2].rlen1=b[i*2].tlen1=0; b[i*2].num0=b[i*2].r-b[i*2].l+1; b[i*2].num1=0; b[i*2+1].llen0=b[i*2+1].rlen0=b[i*2+1].tlen0=b[i*2+1].r-b[i*2+1].l+1; b[i*2+1].llen1=b[i*2+1].rlen1=b[i*2+1].tlen1=0; b[i*2+1].num0=b[i*2+1].r-b[i*2+1].l+1; b[i*2+1].num1=0; } else if(b[i].cnt==1){ b[i*2].llen0=b[i*2].rlen0=b[i*2].tlen0=0; b[i*2].llen1=b[i*2].rlen1=b[i*2].tlen1=b[i*2].r-b[i*2].l+1; b[i*2].num0=0; b[i*2].num1=b[i*2].r-b[i*2].l+1; b[i*2+1].llen0=b[i*2+1].rlen0=b[i*2+1].tlen0=0; b[i*2+1].llen1=b[i*2+1].rlen1=b[i*2+1].tlen1=b[i*2+1].r-b[i*2+1].l+1; b[i*2+1].num0=0; b[i*2+1].num1=b[i*2+1].r-b[i*2+1].l+1; } b[i].cnt=-1; } if(b[i].yihuo!=0){ b[i*2].yihuo=1^b[i*2].yihuo; swap(b[i*2].llen0,b[i*2].llen1); swap(b[i*2].rlen0,b[i*2].rlen1); swap(b[i*2].tlen0,b[i*2].tlen1); swap(b[i*2].num0,b[i*2].num1); /* if(b[i*2].cnt!=-1){ 这里和下面注释的不能写,因为如果换了的话就和父亲节点的信息不同了 b[i*2].cnt^=1; } */ b[i*2+1].yihuo=1^b[i*2+1].yihuo; swap(b[i*2+1].llen0,b[i*2+1].llen1); swap(b[i*2+1].rlen0,b[i*2+1].rlen1); swap(b[i*2+1].tlen0,b[i*2+1].tlen1); swap(b[i*2+1].num0,b[i*2+1].num1); /* if(b[i*2+1].cnt!=-1){ b[i*2+1].cnt^=1; } */ b[i].yihuo=0; } } void pushup(int i) { if(b[i].l==b[i].r)return; b[i].num0=b[i*2].num0+b[i*2+1].num0; b[i].num1=b[i*2].num1+b[i*2+1].num1; b[i].llen0=b[i*2].llen0; b[i].rlen0=b[i*2+1].rlen0; if(b[i*2].llen0==b[i*2].r-b[i*2].l+1){ b[i].llen0+=b[i*2+1].llen0; } if(b[i*2+1].rlen0==b[i*2+1].r-b[i*2+1].l+1){ b[i].rlen0+=b[i*2].rlen0; } b[i].tlen0=max(b[i*2].tlen0,b[i*2+1].tlen0); b[i].tlen0=max(b[i*2].rlen0+b[i*2+1].llen0,b[i].tlen0); b[i].llen1=b[i*2].llen1; b[i].rlen1=b[i*2+1].rlen1; if(b[i*2].llen1==b[i*2].r-b[i*2].l+1){ b[i].llen1+=b[i*2+1].llen1; } if(b[i*2+1].rlen1==b[i*2+1].r-b[i*2+1].l+1){ b[i].rlen1+=b[i*2].rlen1; } b[i].tlen1=max(b[i*2].tlen1,b[i*2+1].tlen1); b[i].tlen1=max(b[i*2].rlen1+b[i*2+1].llen1,b[i].tlen1); } void build(int l,int r,int i) { int mid; b[i].l=l;b[i].r=r;b[i].yihuo=0;b[i].cnt=-1; if(l==r){ if(a[l]==0){ b[i].llen0=b[i].rlen0=b[i].tlen0=1; b[i].llen1=b[i].rlen1=b[i].tlen1=0; b[i].num0=1; b[i].num1=0; } else{ b[i].llen0=b[i].rlen0=b[i].tlen0=0; b[i].llen1=b[i].rlen1=b[i].tlen1=1; b[i].num0=0; b[i].num1=1; } return; } mid=(l+r)/2; build(l,mid,i*2); build(mid+1,r,i*2+1); pushup(i); } void update01(int l,int r,int num,int i) { int mid; if(b[i].l==l && b[i].r==r){ b[i].yihuo=0; b[i].cnt=num; if(num==0){ b[i].llen0=b[i].rlen0=b[i].tlen0=b[i].r-b[i].l+1; b[i].llen1=b[i].rlen1=b[i].tlen1=0; b[i].num0=b[i].r-b[i].l+1; b[i].num1=0; } else{ b[i].llen0=b[i].rlen0=b[i].tlen0=0; b[i].llen1=b[i].rlen1=b[i].tlen1=b[i].r-b[i].l+1; b[i].num0=0; b[i].num1=b[i].r-b[i].l+1; } return; } pushdown(i); mid=(b[i].l+b[i].r)/2; if(r<=mid)update01(l,r,num,i*2); else if(l>mid)update01(l,r,num,i*2+1); else{ update01(l,mid,num,i*2); update01(mid+1,r,num,i*2+1); } pushup(i); } void update2(int l,int r,int i) { int mid; if(b[i].l==l && b[i].r==r){ b[i].yihuo=1^b[i].yihuo; swap(b[i].llen0,b[i].llen1); swap(b[i].rlen0,b[i].rlen1); swap(b[i].tlen0,b[i].tlen1); swap(b[i].num0,b[i].num1); //if(b[i].cnt!=-1)b[i].cnt^=1;这句不用写 return; } pushdown(i);//pushdown(i)放上面下面都行的 mid=(b[i].l+b[i].r)/2; if(r<=mid)update2(l,r,i*2); else if(l>mid)update2(l,r,i*2+1); else{ update2(l,mid,i*2); update2(mid+1,r,i*2+1); } pushup(i); } void question1(int l,int r,int i) { int mid; if(b[i].l==l && b[i].r==r){ num1+=b[i].num1; return; } pushdown(i); mid=(b[i].l+b[i].r)/2; if(r<=mid)question1(l,r,i*2); else if(l>mid)question1(l,r,i*2+1); else{ question1(l,mid,i*2); question1(mid+1,r,i*2+1); } } int question2(int l,int r,int i) { int mid; if(b[i].l==l && b[i].r==r){ return b[i].tlen1; } pushdown(i); mid=(b[i].l+b[i].r)/2; if(r<=mid){ return question2(l,r,i*2); } else if(l>mid){ return question2(l,r,i*2+1); } else{ int l1,r1; l1=max(b[i*2].r-b[i*2].rlen1+1,l); r1=min(b[i*2+1].l+b[i*2+1].llen1-1,r); int temp=r1-l1+1; temp=max(temp,question2(l,mid,i*2) ); temp=max(temp,question2(mid+1,r,i*2+1)); return temp; } } int main() { int n,m,i,j,T,f,c,d; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++){ scanf("%d",&a[i]); } build(1,n,1); for(i=1;i<=m;i++){ scanf("%d%d%d",&f,&c,&d); c++;d++; if(f==0){ update01(c,d,0,1); } if(f==1){ update01(c,d,1,1); } else if(f==2){ update2(c,d,1); } else if(f==3){ num1=0; question1(c,d,1); printf("%d\n",num1); } else if(f==4){ printf("%d\n",question2(c,d,1)); } } } return 0; }