【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 }


不压行也就一百一二十行吧。

猜你喜欢

转载自www.cnblogs.com/Judge/p/9894026.html