1. 程式人生 > >bzoj1858 [Scoi2010]序列操作——線段樹

bzoj1858 [Scoi2010]序列操作——線段樹

div 原因 problem 操作 mes AI ret IV rev

題目: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; }

bzoj1858 [Scoi2010]序列操作——線段樹