题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1858
线段树...调了一个上午...(后面带 // 的都是改出来的)
lazy 标记的下放好麻烦,还得考虑赋值和取反的先后顺序什么的...
因为在取反时把赋值标记 swap 了,所以下放的时候先判断取反再判断赋值...
而且WA了一上午的原因竟然是一开始不慎把取反以为成翻转了,后来没改干净...那个 rev 的名字啊...
总之没有太改变自己最初的想法、改了些细节就A了还是很高兴的!
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int const maxn=1e5+5; int n,m,op,a,b,c[maxn]; struct N{ int sum,z[3],y[3],m[3]; int lz[3],rev,len; }t[maxn<<2]; int rd() { int ret=0;char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return ret; } void pushup(int x) { int ls=(x<<1),rs=(x<<1|1); t[x].sum=t[ls].sum+t[rs].sum; for(int i=0;i<=1;i++) { t[x].z[i]=t[ls].z[i]+(t[ls].z[i]==t[ls].len?t[rs].z[i]:0); t[x].y[i]=t[rs].y[i]+(t[rs].y[i]==t[rs].len?t[ls].y[i]:0); // t[x].m[i]=max(max(t[x].z[i],t[x].y[i]),t[ls].y[i]+t[rs].z[i]);// t[x].m[i]=max(max(t[ls].m[i],t[rs].m[i]),t[ls].y[i]+t[rs].z[i]);// } } void upt(int x,int val)//赋值 { t[x].lz[val]=1; t[x].lz[!val]=0; t[x].rev=0;//! t[x].sum=t[x].len*val; t[x].z[val]=t[x].y[val]=t[x].m[val]=t[x].len; t[x].z[!val]=t[x].y[!val]=t[x].m[!val]=0; } void re(int x)//取反 { swap(t[x].z[0],t[x].z[1]); swap(t[x].y[1],t[x].y[0]);//!!! swap(t[x].m[1],t[x].m[0]); t[x].sum=t[x].len-t[x].sum; t[x].rev^=1; swap(t[x].lz[1],t[x].lz[0]);//! } void pushdown(int x) { // if(t[x].len==1)return;// int ls=(x<<1),rs=(x<<1|1); if(t[x].rev)t[x].rev^=1,re(ls),re(rs); for(int v=0;v<=1;v++) if(t[x].lz[v])t[x].lz[v]=0,upt(ls,v),upt(rs,v);//顺序 } void build(int x,int l,int r) { t[x].len=r-l+1; if(l==r) { t[x].z[c[l]]=t[x].y[c[l]]=t[x].m[c[l]]=1; t[x].sum=c[l]; // return; } int mid=((l+r)>>1); build(x<<1,l,mid); build(x<<1|1,mid+1,r); pushup(x); } void update(int x,int l,int r,int L,int R,int val) { if(l>=L&&r<=R) { upt(x,val);return; } pushdown(x); int mid=((l+r)>>1); if(mid>=L)update(x<<1,l,mid,L,R,val); if(mid<R)update(x<<1|1,mid+1,r,L,R,val); pushup(x); } void rever(int x,int l,int r,int L,int R) { if(l>=L&&r<=R) { re(x);return; } int mid=((l+r)>>1); pushdown(x); if(mid>=L)rever(x<<1,l,mid,L,R); if(mid<R)rever(x<<1|1,mid+1,r,L,R); pushup(x); } int query(int x,int l,int r,int L,int R) { if(l>=L&&r<=R)return t[x].sum; int mid=((l+r)>>1),ret=0; pushdown(x); if(mid>=L)ret+=query(x<<1,l,mid,L,R); if(mid<R)ret+=query(x<<1|1,mid+1,r,L,R); return ret; } int ask(int x,int l,int r,int L,int R) { if(l>=L&&r<=R)return t[x].m[1]; pushdown(x);// int mid=((l+r)>>1); if(mid>=R)return ask(x<<1,l,mid,L,R); if(mid<L)return ask(x<<1|1,mid+1,r,L,R); int ret=0; ret=max(ask(x<<1,l,mid,L,R),ask(x<<1|1,mid+1,r,L,R)); ret=max(ret,min(t[x<<1].y[1],mid-L+1)+min(t[x<<1|1].z[1],R-mid)); return ret; } int main() { n=rd();m=rd(); for(int i=1;i<=n;i++)c[i]=rd(); build(1,1,n); while(m--) { op=rd(); a=rd()+1; b=rd()+1; if(op==0||op==1)update(1,1,n,a,b,op); if(op==2)rever(1,1,n,a,b); if(op==3)printf("%d\n",query(1,1,n,a,b)); if(op==4)printf("%d\n",ask(1,1,n,a,b)); } return 0; }