bzoj 1500 维修数列

Splay的BOSS级别的题目,几乎包含了所有区间维护的操作,对于想要提高代码熟练度的人来说这个题非常值得一写。

首先我们要维护的域是:size,sum,la(左max),ra(右max),ma(整体max)更新的时候用这些域更新就行,注意下传的时候也要更新响应域值。

对于那些恶心操作,我就挨个说一下吧:

注:标准结构:区间右端点+1(R)为根,区间左端点-1(L)为根的左儿子,这样目标区间就是L的右儿子,这种形式以后都用"标准结构"代替。

插入操作:先把需要插入的序列建成一个小平衡树(递归),转出标准结构,插到L的右儿子上就行了。

删除操作:转出标准结构,把L的右儿子切下来就行了(注意因为要回收空间,所以还是把要切的子树遍历了一遍,把这颗树上的节点标号入栈)。

覆盖操作:转出标准结构,把L的右儿子打上覆盖标记cov(以后下传的时候把节点的值改为cov的值,sum变为cov*size,la=ra=ma变为cov和sum中较大的一个,因为有负数的情况)

翻转操作:转出标准结构,把L的右儿子打上翻转标记rev(以后下传的时候要交换左右儿子并且交换la和ra)

求和操作:转出标准结构,答案就是L的右儿子的sum

最大值操作:转出标准结构,答案就是L的右儿子的ma

区间操作的时候一定要明白一点,就是打标记的同时做修改,就是说当一个点带了标记的时候,它已经被修改过了。

这个题还是做了我不少时间的。

repairnum
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<cstring>
  6 #define maxn 1000000
  7 #define inf 2147483646
  8 using namespace std;
  9 int c[maxn][2],fa[maxn];
 10 int a[maxn],key[maxn],sum[maxn],la[maxn],ra[maxn],ma[maxn],cov[maxn],size[maxn];
 11 int q[maxn];
 12 bool rev[maxn];
 13 int n,m,tot,num,rot,st,ed,tail;
 14 
 15 void update(int x)
 16 {
 17         if (!x) return;
 18         la[x]=max(la[c[x][0]],sum[c[x][0]]+key[x]+max(0,la[c[x][1]]));
 19         ra[x]=max(ra[c[x][1]],sum[c[x][1]]+key[x]+max(0,ra[c[x][0]]));
 20         ma[x]=max(max(ma[c[x][0]],ma[c[x][1]]),key[x]+max(0,ra[c[x][0]])+max(0,la[c[x][1]]));
 21         sum[x]=sum[c[x][0]]+sum[c[x][1]]+key[x];
 22         size[x]=size[c[x][0]]+size[c[x][1]]+1;
 23 }
 24 
 25 void reverse(int x)
 26 {
 27         if (!x) return;
 28         swap(c[x][0],c[x][1]);
 29         swap(la[x],ra[x]);
 30         rev[x]^=1;
 31 }
 32 
 33 void recover(int x,int z)
 34 {
 35         if (!x) return ;
 36         key[x]=cov[x]=z;
 37         sum[x]=size[x]*z;
 38         la[x]=ra[x]=ma[x]=max(z,sum[x]);
 39 }
 40 
 41 void down(int x)
 42 {
 43         if (!x) return;
 44         if (rev[x])
 45         {
 46                 reverse(c[x][0]);
 47                 reverse(c[x][1]);
 48                 rev[x]=0;
 49         }
 50         if (cov[x]!=-inf)
 51         {
 52                 recover(c[x][0],cov[x]);
 53                 recover(c[x][1],cov[x]);
 54                 cov[x]=-inf;
 55         }
 56 }
 57 
 58 void relax(int x,int rot)
 59 {
 60         if (x!=rot) relax(fa[x],rot);
 61         down(x);
 62 }
 63 
 64 void rotate(int x,int &rot)
 65 {
 66         int y=fa[x],z=fa[y];
 67         int p=(c[y][1]==x),q=p^1;
 68         if (y==rot) rot=x; 
 69         else if (c[z][0]==y) c[z][0]=x; else c[z][1]=x;
 70         fa[x]=z; fa[y]=x; fa[c[x][q]]=y;
 71         c[y][p]=c[x][q]; c[x][q]=y;
 72         update(y);
 73 }
 74 
 75 void splay(int x,int &rot)
 76 {
 77         relax(x,rot);
 78         while (x!=rot)
 79         {
 80                 int y=fa[x], z=fa[y];
 81                 if (y!=rot)
 82                         if ((c[y][0]==x)xor(c[z][0]==y)) rotate(x,rot); else rotate(y,rot);
 83                 rotate(x,rot);
 84         }
 85         update(x);
 86 }
 87 
 88 int pick()
 89 {
 90         if (tail) return q[tail--];
 91         else return ++num;
 92 }
 93 
 94 int setup(int x)
 95 {
 96         int t=pick();
 97         key[t]=a[x];
 98         cov[t]=-inf;
 99         rev[t]=0;
100         la[t]=ra[t]=ma[t]=-inf;
101         return t;
102 }
103 
104 int build(int l,int r)
105 {
106         int mid=(l+r)>>1,left=0,right=0;
107         if (l<mid)      left=build(l,mid-1);
108         int t=setup(mid);
109         if (r>mid)      right=build(mid+1,r);
110         if (left)       c[t][0]=left,fa[left]=t;
111         if (right)c[t][1]=right,fa[right]=t;
112         update(t);
113         return t;
114 }
115 
116 int find(int t,int k)
117 {
118         down(t);
119         if (k==size[c[t][0]]+1) return t;
120         if (k<size[c[t][0]]+1) return find(c[t][0],k);
121         if (k>size[c[t][0]]+1) return find(c[t][1],k-size[c[t][0]]-1);
122 }
123 
124 void del(int &x)
125 {
126         if (!x) return;
127         q[++tail]=x;
128         fa[x]=0;
129         del(c[x][0]);
130         del(c[x][1]);
131         la[x]=ra[x]=ma[x]=-inf;
132         x=0;
133 }
134 
135 int main()
136 {
137         //freopen("build.in","r",stdin);
138         //freopen("build.out","w",stdout);
139         scanf("%d %d",&n,&m);
140         for (int i=2;i<=n+1;i++)
141         {
142                 scanf("%d",&a[i]);      
143         }
144         a[st=1]=0; a[ed=n+2]=0;
145         ra[0]=la[0]=ma[0]=-inf;
146         rot=build(1,n+2);
147         char sign[20];
148         int x,y,l,r,z,ans;
149         for (int i=1;i<=m;i++)
150         {
151                 scanf("%s",&sign);
152                 if (sign[0]=='I')
153                 {
154                         scanf("%d %d",&x,&y);
155                         l=find(rot,x+1); r=find(rot,x+2);
156                         splay(r,rot); splay(l,c[rot][0]);
157                         for (int j=1;j<=y;j++) 
158                                 scanf("%d",&a[j]);
159                         int tmp=build(1,y);
160                         fa[tmp]=l; c[l][1]=tmp;                 
161                         update(l); update(r);
162                 }
163                 if (sign[0]=='D')
164                 {
165                         scanf("%d %d",&x,&y);
166                         l=find(rot,x);  r=find(rot,x+y+1);
167                         splay(r,rot); splay(l,c[rot][0]);
168                         del(c[l][1]);
169                         update(l); update(r);
170                 }                       
171                 if (sign[0]=='M'&&sign[2]=='K')
172                 {
173                         scanf("%d %d %d",&x,&y,&z);
174                         l=find(rot,x); r=find(rot,x+y+1);
175                         splay(r,rot); splay(l,c[rot][0]);
176                         recover(c[l][1],z);
177                 }
178                 if (sign[0]=='R')
179                 {
180                         scanf("%d %d",&x,&y);
181                         l=find(rot,x); r=find(rot,x+y+1);
182                         splay(r,rot); splay(l,c[rot][0]);
183                         reverse(c[l][1]);
184                 }
185                 if (sign[0]=='G')
186                 {
187                         scanf("%d %d",&x,&y);
188                         l=find(rot,x); r=find(rot,x+y+1);
189                         splay(r,rot); splay(l,c[rot][0]);
190                         ans=sum[c[l][1]];
191                         printf("%d\n",ans);
192                 }
193                 if (sign[0]=='M'&&sign[2]=='X')
194                 {
195                         splay(ed,rot); splay(st,c[rot][0]);
196                         ans=ma[c[st][1]];
197                         printf("%d\n",ans);
198                 }
199                 //for(int i=1;i<=num;i++) cout<<find(rot,i)<<' ';cout<<"\n";
200                 //for (int i=1;i<=num;i++) cout<<i<<' '<<size[i]<<' '<<fa[i]<<' '<<c[i][0]<<' '<<c[i][1]<<' '<<la[i]<<' '<<ra[i]<<' '<<ma[i]<<' '<<sum[i]<<endl;
201         }
202         return 0;
203 }

 

转载于:https://www.cnblogs.com/zig-zag/archive/2013/03/28/2987390.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值