【SCOI2010】序列操作
各种繁琐的线段树标记操作。。。赤裸裸的码农题。
调了一个晚上,最后写篇题解。
题解亮点:代码短,~~跑得慢(连第一页都没挤进去)~~
其实我跟你们说啊,代码短是好事~~(这里不是说压行好,我的代码不压行也没那么长)~~,因为代码短好调啊,几个类似的语句写个函数,既满足了懒人需要(减少码量),而且也让代码思路清晰,没有那么杂乱了。
the code:
1 //by Judge 2 #include<cstdio> 3 #include<iostream> 4 using namespace std; 5 const int M=2e5+5; 6 #ifndef Judge 7 #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 8 #endif 9 char buf[1<<21],*p1=buf,*p2=buf; 10 inline int read(){ int x=0,f=1; char c=getchar(); 11 for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; 12 for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; 13 } char sr[1<<21],z[20];int C=-1,Z; 14 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} 15 inline void print(int x,char chr='\n'){ 16 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x; 17 while(z[++Z]=x%10+48,x/=10); 18 while(sr[++C]=z[Z],--Z);sr[++C]=chr; 19 } inline void cmax(int& a,int b){ if(a<b) a=b; } 20 struct node{ int l,r,len,tag,rev; 21 int sum,max[2],lmax[2],rmax[2]; 22 }t[M<<2],zero; int n,m,v[M]; 23 #define ls k<<1 24 #define rs k<<1|1 25 inline node merge(node a,node b){ //懒人合并 26 static node c; 27 c.sum=a.sum+b.sum; 28 for(int i=0;i<=1;++i){ 29 c.lmax[i]=a.lmax[i]; 30 if(a.lmax[i]==a.len) 31 c.lmax[i]+=b.lmax[i]; 32 c.rmax[i]=b.rmax[i]; 33 if(b.rmax[i]==b.len) 34 c.rmax[i]+=a.rmax[i]; 35 c.max[i]=a.rmax[i]+b.lmax[i]; 36 cmax(c.max[i],a.max[i]); 37 cmax(c.max[i],b.max[i]); 38 } return c; 39 } inline void pushup(int k){ //懒人pushup 40 t[0]=merge(t[ls],t[rs]); 41 t[k].sum=t[0].sum; 42 for(int i=0;i<=1;++i){ 43 t[k].max[i]=t[0].max[i]; 44 t[k].lmax[i]=t[0].lmax[i]; 45 t[k].rmax[i]=t[0].rmax[i]; 46 } 47 } inline void chg(int k,int v){ //懒人change 48 if(v<2){ 49 t[k].sum=t[k].len*v,t[k].tag=v,t[k].rev=0; 50 t[k].max[v]=t[k].lmax[v]=t[k].rmax[v]=t[k].len; 51 t[k].max[v^1]=t[k].lmax[v^1]=t[k].rmax[v^1]=0; 52 } else if(v==2){ 53 t[k].sum=t[k].len-t[k].sum; 54 if(t[k].tag!=-1) t[k].tag^=1; 55 else t[k].rev^=1; 56 swap(t[k].max[0],t[k].max[1]); 57 swap(t[k].lmax[0],t[k].lmax[1]); 58 swap(t[k].rmax[0],t[k].rmax[1]); 59 } 60 } inline void pushdown(int k){ //pushdown可以非常短 61 if(t[k].tag!=-1) 62 t[k].rev=0,chg(ls,t[k].tag), 63 chg(rs,t[k].tag),t[k].tag=-1; 64 else if(t[k].rev) 65 chg(ls,2),chg(rs,2),t[k].rev=0; 66 } void build(int k,int l,int r){ /* 然后都是线段树常规操作 */ 67 t[k].l=l,t[k].r=r,t[k].len=r-l+1,t[k].tag=-1; 68 if(l==r){ int c=v[l]; t[k].sum=c; 69 t[k].max[c]=t[k].lmax[c]=t[k].rmax[c]=1; return ; 70 } int mid=l+r>>1; build(ls,l,mid),build(rs,mid+1,r),pushup(k); 71 } void update(int k,int L,int R,int opt){ 72 if(L<=t[k].l&&t[k].r<=R) return chg(k,opt); 73 int mid=t[k].l+t[k].r>>1; pushdown(k); 74 if(L<=mid) update(ls,L,R,opt); 75 if(R>mid) update(rs,L,R,opt); pushup(k); 76 } int query(int k,int L,int R){ 77 if(L>t[k].r||t[k].l>R) return 0; 78 if(L<=t[k].l&&t[k].r<=R) return t[k].sum; 79 pushdown(k); int mid=t[k].l+t[k].r>>1; 80 return query(ls,L,R)+query(rs,L,R); 81 } node query_mx(int k,int L,int R){ 82 if(L>t[k].r||t[k].l>R) return zero; //zero作用和他的名字一样,merge的时候就不算贡献了 83 if(L<=t[k].l&&t[k].r<=R) return t[k]; pushdown(k); 84 return merge(query_mx(ls,L,R),query_mx(rs,L,R)); 85 } int main(){ n=read(),m=read(); 86 for(int i=1;i<=n;++i) v[i]=read(); 87 build(1,1,n); 88 for(int opt,l,r;m;--m){ //处理各种操作 89 opt=read(),l=read()+1,r=read()+1; 90 if(opt<3) update(1,l,r,opt); 91 else if(opt==3) print(query(1,l,r)); 92 else if(opt==4) print(query_mx(1,l,r).max[1]); 93 } return Ot(),0; 94 }
不压行也就一百一二十行吧。