bzoj 1500 [NOI 2005] 维修数列

题目大意不多说了

貌似每个苦逼的acmer都要做一下这个splay树的模版题目吧

还是有很多操作的,估计够以后当模版了。。。。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cmath>
  6 
  7 using namespace std;
  8 const int N = 1000010;
  9 const int INF = 0x3f3f3f3f;
 10 #define ls ch[x][0]
 11 #define rs ch[x][1]
 12 
 13 struct SplayTree{
 14     int ch[N][2] , pre[N];
 15     int ml[N] , mr[N] , mm[N]; //区间最大
 16     int val[N] , sz[N] , sum[N] , size , rt;
 17     int rev[N] , to[N]; // lazy标记
 18     int del[N] , top; //内部保存删除的数的位置,然后可以从其中提取位置给新进入的元素
 19     int a[N];
 20 
 21     void push_up(int x)
 22     {
 23         sz[x] = sz[ls]+sz[rs]+1;
 24         sum[x] = sum[ls]+sum[rs]+val[x];
 25         /*********************/
 26         ml[x] = max(ml[ls] , sum[ls]+val[x]+max(ml[rs] , 0));
 27         mr[x] = max(mr[rs] , sum[rs]+val[x]+max(mr[ls] , 0));
 28         mm[x] = max(mm[ls] , max(mm[rs] , max(ml[rs],0)+max(mr[ls],0)+val[x]));
 29         /*********************/
 30     }
 31 
 32     void push_down(int x)
 33     {
 34         if(rev[x]){
 35             if(ls){
 36                 rev[ls]^=1 ;
 37                 swap(ml[ls] , mr[ls]);
 38             }
 39             if(rs){
 40                 rev[rs]^=1 ;
 41                 swap(ml[rs] , mr[rs]);
 42             }
 43             swap(ls , rs);
 44             rev[x] = 0;
 45         }
 46         /**to[x]的初始化要注意**/
 47         if(to[x]!=-INF){
 48             if(ls){
 49                 sum[ls] = sz[ls]*to[x];
 50                 ml[ls] = mr[ls] = mm[ls] = max(sum[ls] , to[x]);
 51                 val[ls] = to[ls] = to[x];
 52             }
 53             if(rs){
 54                 sum[rs] = sz[rs]*to[x];
 55                 ml[rs] = mr[rs] = mm[rs] = max(sum[rs] , to[x]);
 56                 val[rs] = to[rs] = to[x];
 57             }
 58             to[x] = -INF;
 59         }
 60     }
 61 
 62     void newNode(int &x , int fa , int v)
 63     {
 64         if(top != -1)
 65             x = del[top--];
 66         else x = ++size;
 67         ch[x][0] = ch[x][1] = 0;
 68         pre[x] = fa;
 69         val[x] = v , sz[x] = 1;
 70         sum[x] = ml[x] = mr[x] = mm[x] = val[x];
 71         rev[x] = 0 , to[x] = -INF;
 72     }
 73 
 74     void build(int &x , int l , int r , int fa)
 75     {
 76         if(l>r) return;
 77         int m=(l+r)>>1;
 78         newNode(x , fa , a[m]);
 79         build(ls , l , m-1 , x);
 80         build(rs , m+1 , r , x);
 81         push_up(x);
 82     }
 83 
 84     void init(int n)
 85     {
 86         /*****因为所有点的最终叶子节点都下标设为了0,所以0上的数据要不影响整棵树*****/
 87         sz[0] = sum[0] = ch[0][0] = ch[0][1] = val[0] = pre[0] = 0;
 88         to[0] = ml[0] = mr[0] = mm[0] = -INF;
 89         rev[0] = 0;
 90         top = -1 , rt = size = 0;
 91         newNode(rt , 0 , -INF);
 92         newNode(ch[rt][1] , rt , -INF);
 93         build(ch[ch[rt][1]][0] , 1 , n , ch[rt][1]);
 94         push_up(ch[rt][1]);
 95         push_up(rt);
 96     }
 97 
 98     void Rotate(int x , int f)
 99     {
100         int y=pre[x] , z=pre[y];
101         /**y要旋转到下方,下传lazy标记**/
102         push_down(y);
103         ch[y][!f] = ch[x][f] , pre[ch[x][f]] = y;
104         ch[x][f] = y , pre[y] = x;
105         ch[z][ch[z][1]==y] = x , pre[x]=z;
106         push_up(y);
107         push_up(x);
108     }
109 
110     void Splay(int x , int goal)
111     {
112         while(pre[x] != goal){
113             if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0]==x);
114             else{
115                 int y = pre[x] , z = pre[y];
116                 int f = ch[z][0] == y;
117                 if(ch[y][f] == x) Rotate(x , !f);
118                 else Rotate(y,f);
119                 Rotate(x , f);
120             }
121         }
122         push_up(x);
123         if(goal == 0) rt = x;
124     }
125 
126     int Select(int pos)
127     {
128         int x = rt;
129         push_down(x);
130         while(sz[ls]+1 != pos){
131             if(sz[ls]+1>pos) x=ls;
132             else{
133                 pos = pos-sz[ls]-1;
134                 x = rs;
135             }
136             push_down(x);
137         }
138         return x;
139     }
140     /***从pos位置之后插入cnt个值***/
141     void Insert(int pos , int cnt)
142     {
143         int x = Select(pos);
144         Splay(x , 0);
145         int y = Select(pos+1);
146         Splay(y , x);
147         build(ch[y][0] , 1 , cnt , y);
148         /***这里build将a[1~cnt]插入到splay树中,要push_up更新***/
149         push_up(y);
150         push_up(x);
151     }
152     /***回收被删除的数的位置***/
153     void Recycle(int x)
154     {
155         if(x){
156             del[++top]=x;
157             Recycle(ls);
158             Recycle(rs);
159         }
160     }
161 
162     void Delete(int s , int t)
163     {
164         int x = Select(s-1) , y = Select(t+1);
165         Splay(x , 0) , Splay(y , x);
166         Recycle(ch[y][0]);
167         ch[y][0] = 0;
168         /***这里y的左子树删除,明显子树数据改变,所以要重新push_up更新数据***/
169         push_up(y);
170         push_up(x);
171     }
172     /****将s~t区间内的所有值都修改为v****/
173     void update(int s , int t , int v)
174     {
175         int x = Select(s-1) , y = Select(t+1);
176         Splay(x , 0) , Splay(y , x);
177         int ptr = ch[y][0];
178         to[ptr]=v;
179         val[ptr]=v;
180         sum[ptr]=v*sz[ptr];
181         ml[ptr] = mr[ptr] = mm[ptr] = max(sum[ptr] , v);
182         return ;
183     }
184 
185     void Reverse(int s , int t)
186     {
187         int x = Select(s-1) , y = Select(t+1);
188         Splay(x , 0) , Splay(y , x);
189         int ptr = ch[y][0];
190         rev[ptr]^=1;
191         swap(ml[ptr] , mr[ptr]);
192     }
193 
194     int querySum(int s , int t)
195     {
196         int x = Select(s-1) , y =  Select(t+1);
197        // cout<<"x: "<<x<<" y: "<<y<<endl;
198         Splay(x , 0) , Splay(y , x);
199         return sum[ch[y][0]];
200     }
201 
202     int queryMax()
203     {
204         int x = Select(1) , y = Select(sz[rt]);
205         Splay(x , 0) , Splay(y , x);
206         return mm[ch[y][0]];
207     }
208 }spt;
209 int main()
210 {
211   //  freopen("a.in" , "r" , stdin);
212     int n , m;
213     char str[20] ;
214     int s , t , v , pos , k;
215     while(~scanf("%d%d" , &n , &m))
216     {
217         for(int i=1 ; i<=n ; i++) scanf("%d" , &spt.a[i]);
218         spt.init(n);
219         /*
220         for(int i=0 ; i<=spt.size ; i++){
221             cout<<"i: "<<i<<" sum: "<<spt.sum[i]<<" l: "<<spt.ch[i][0]<<" lv: "<<spt.val[spt.ch[i][0]]<<" r: "<<spt.ch[i][1]<<" rv: "<<spt.val[spt.ch[i][1]]<<endl;
222         }*/
223         for(int i=0 ; i<m ; i++){
224             scanf("%s" , str);
225             if(str[0] == 'I'){
226                 scanf("%d%d" , &pos , &k);
227                 for(int i=1 ; i<=k ; i++) scanf("%d" , &spt.a[i]);
228                 spt.Insert(pos+1 , k);
229             }
230             else if(str[0]=='D'){
231                 scanf("%d%d" , &pos , &k);
232                 spt.Delete(pos+1 , pos+k);
233             }
234             else if(str[0] == 'M' && str[2] == 'K'){
235                 scanf("%d%d%d" , &pos , &k , &v);
236                 spt.update(pos+1 , pos+k , v);
237             }
238             else if(str[0] == 'R'){
239                 scanf("%d%d" , &pos , &k);
240                 spt.Reverse(pos+1 , pos+k);
241             }
242             else if(str[0] == 'G'){
243                 scanf("%d%d" , &pos , &k);
244                 printf("%d
" , spt.querySum(pos+1 , pos+k));
245             }
246             else{
247                 /****这里不能直接用spt.mm[rt]作为答案,因为为了方便查询,
248                 我们增加了两个不包含在本身数组的点,直接spt.mm[rt]会把这两个点也算进来***/
249                 printf("%d
" , spt.queryMax());
250             }
251         }
252     }
253     return 0;
254 }
原文地址:https://www.cnblogs.com/CSU3901130321/p/4446054.html