这道题很麻烦,比较烦的是题目其实没什么含金量,就是延迟标记加区间合并。
昨天晚上一点半被蚊子咬得睡不着,就起来做这个题。从一点半做到快三点,提交wa。当时我就去睡了,早上来继续debug。
做一个小修改之后,试探性地提交了一次,无悬念wa。后来又debug了半天,终于找到一个藏得很深的错误,提交后796msAC。
题目麻烦的是我们求的是最长的1的连续序列,但是因为题目中的操作是一个异或操作,所以还得记录0的信息。在更新节点信息的时候,要将1转环为0,0转换为1。别的地方就是线段树的两种基本操作了。
#include#include #define N 100005 struct node { int x,y; int flag; int ll,lr; int max1,max0; int lflag,rflag; }a[N*3]; int b[N]; int Max(int x,int y) { if(x>y) return x; else return y; } int Min(int x,int y) { if(x mid) InsertTree(temp+1,x,y); else { InsertTree(temp,x,mid); InsertTree(temp+1,mid+1,y); } int tt=0; if(a[temp].rflag==a[temp+1].lflag) tt=a[temp].lr+a[temp+1].ll; if(a[temp].rflag==0&&tt) a[t].max0=Max(tt,Max(a[temp].max0,a[temp+1].max0)); else a[t].max0=Max(a[temp].max0,a[temp+1].max0); if(a[temp].rflag==1&&tt) a[t].max1=Max(tt,Max(a[temp].max1,a[temp+1].max1)); else a[t].max1=Max(a[temp].max1,a[temp+1].max1); if(a[temp].ll==a[temp].y-a[temp].x+1&&tt) a[t].ll=tt; else a[t].ll=a[temp].ll; a[t].lflag=a[temp].lflag; if(a[temp+1].lr==a[temp+1].y-a[temp+1].x+1&&tt) a[t].lr=tt; else a[t].lr=a[temp+1].lr; a[t].rflag=a[temp+1].rflag; //printf("%d %d %d %d\n",a[t].x,a[t].y,a[t].max0,a[t].max1); return ; } int FindTree(int t,int x,int y) { if(a[t].x==x&&a[t].y==y) return a[t].max1; int temp=t*2; int mid=(a[t].x+a[t].y)/2; if(a[t].flag) { ChangeTree(temp); ChangeTree(temp+1); a[t].flag=0; } if(y<=mid) return FindTree(temp,x,y); else if(x>mid) return FindTree(temp+1,x,y); else { int tt,lt,rt; if(a[temp].rflag==a[temp+1].lflag&&a[temp].rflag) { lt=Min(a[temp].lr,mid-x+1); rt=Min(a[temp+1].ll,y-mid); tt=lt+rt; return Max(tt,Max(FindTree(temp,x,mid),FindTree(temp+1,mid+1,y))); } else return Max(FindTree(temp,x,mid),FindTree(temp+1,mid+1,y)); } return 0; } int main() { int n; while(scanf("%d",&n)!=EOF) { int i; CreatTree(1,1,n); for(i=1;i<=n;i++) { scanf("%d",&b[i]); if(b[i]) InsertTree(1,i,i); } int m; scanf("%d",&m); while(m--) { int x,y,z; scanf("%d%d%d",&x,&y,&z); if(x==0) printf("%d\n",FindTree(1,y,z)); else InsertTree(1,y,z); } } return 0; }