这题真的呵呵了。敲了很长时间,调了很多bug,把0 1 输出,解决了。最后想取反,怎么搞都有bug,
最后还是看了大牛们的博客。不过这题真的敲得爽,调bug时基本把线段树过程全部弄了一遍。
#include<stdio.h> #include<string.h> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define maxn 100010 int mark[maxn<<2];//成端更新用 int rsum[maxn<<2],lsum[maxn<<2],msum[maxn<<2];//来计算连续的最多的1 int numone[maxn<<2];//不连续区间1的个数 int num[maxn<<2];//输入数组 int max(int x,int y) { return x>y?x:y; } int min(int x,int y) { return x<y?x:y; } void pushup(int l,int r,int rt) { int len=r-l+1; int m=(l+r)/2; if(mark[rt<<1]==mark[rt<<1|1]) mark[rt]=mark[rt<<1];//向上更新维护mark else mark[rt]=-1; if(mark[rt]==1) { msum[rt]=lsum[rt]=rsum[rt]=numone[rt]=len;//如果mark为1,表明全要为一 } else if(mark[rt]==0) { numone[rt]=lsum[rt]=msum[rt]=rsum[rt]=0;//类似 } else//如果mark为-1 { lsum[rt]=lsum[rt<<1]; rsum[rt]=rsum[rt<<1|1]; msum[rt]=max(msum[rt<<1],msum[rt<<1|1]); numone[rt]=numone[rt<<1]+numone[rt<<1|1]; if(lsum[rt<<1]==m-l+1)lsum[rt]=lsum[rt<<1]+lsum[rt<<1|1]; if(rsum[rt<<1|1]==r-m)rsum[rt]=rsum[rt<<1|1]+rsum[rt<<1]; msum[rt]=max(msum[rt],lsum[rt<<1|1]+rsum[rt<<1]); } } void pushdown(int l,int r,int rt) { if(mark[rt]!=-1) { mark[rt<<1]=mark[rt<<1|1]=mark[rt]; if(mark[rt]==1) { int len=r-l+1; numone[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=msum[rt<<1]=len-len/2; numone[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=msum[rt<<1|1]=len/2; } else { lsum[rt<<1]=rsum[rt<<1]=msum[rt<<1]=numone[rt<<1]=0; lsum[rt<<1|1]=rsum[rt<<1|1]=msum[rt<<1|1]=numone[rt<<1|1]=0; } mark[rt]=-1; } } void build(int l,int r,int rt) { if(l==r) { numone[rt]=lsum[rt]=rsum[rt]=msum[rt]=mark[rt]=num[l]; return; } int m=(l+r)/2; build(lson); build(rson); pushup(l,r,rt); } void updata(int L,int R,int c,int l,int r,int rt)//更新0 和 1的情况 { if(l>=L&&R>=r) { mark[rt]=c; if(c==0) { lsum[rt]=rsum[rt]=msum[rt]=0; numone[rt]=0; } else if(c==1) { lsum[rt]=rsum[rt]=msum[rt]=r-l+1; numone[rt]=r-l+1; } return ; } pushdown(l,r,rt); int m=(l+r)/2; if(m>=L) updata(L,R,c,lson); if(R>m) updata(L,R,c,rson); pushup(l,r,rt); } void change(int L,int R,int l,int r,int rt)//取反 { if(l>=L&&R>=r&&mark[rt]!=-1) { if(mark[rt]==1) lsum[rt]=msum[rt]=rsum[rt]=numone[rt]=0; else if(mark[rt]==0) lsum[rt]=msum[rt]=rsum[rt]=numone[rt]=r-l+1; mark[rt]^=1; return; } pushdown(l,r,rt); int m=(l+r)/2; if(m>=L) change(L,R,lson); if(R>m) change(L,R,rson); pushup(l,r,rt); } int query(int L,int R,int l,int r,int rt)//查询1的个数 { if(l>=L&&R>=r) { return numone[rt]; } pushdown(l,r,rt); int ret=0; int m=(l+r)/2; if(m>=L) ret+=query(L,R,lson); if(R>m) ret+=query(L,R,rson); return ret; } int queryone(int L,int R,int l,int r,int rt)//查询连续的1长 { if(L<=l&&R>=r) { return msum[rt]; } pushdown(l,r,rt); int ret=-99999999; int m=(l+r)/2; if(m>=L) ret=max(ret,queryone(L,R,lson)); if(R>m) ret=max(ret,queryone(L,R,rson)); ret=max(ret,min(m-L+1,rsum[rt<<1])+min(R-m,lsum[rt<<1|1]));//长度是否合法 return ret; } int main() { int i,n,m,t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++) scanf("%d",&num[i]); build(1,n,1); int x,y,z; while(m--) { scanf("%d%d%d",&x,&y,&z); if(x==0) updata(y+1,z+1,0,1,n,1); else if(x==1) updata(y+1,z+1,1,1,n,1); else if(x==2) change(y+1,z+1,1,n,1); else if(x==3) printf("%d ",query(y+1,z+1,1,n,1)); else if(x==4) printf("%d ",queryone(y+1,z+1,1,n,1)); } } }