题目大意不多说了

貌似每个苦逼的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\n" , spt.querySum(pos+1 , pos+k));
245             }
246             else{
247                 /****这里不能直接用spt.mm[rt]作为答案,因为为了方便查询,
248                 我们增加了两个不包含在本身数组的点,直接spt.mm[rt]会把这两个点也算进来***/
249                 printf("%d\n" , spt.queryMax());
250             }
251         }
252     }
253     return 0;
254 }

转载于:https://www.cnblogs.com/CSU3901130321/p/4446054.html

bzoj 1500 [NOI 2005] 维修数列相关推荐

  1. BZOJ 1502 NOI 2005 月下柠檬树

    题目大意 给定一些圆和梯形,求它们面积的并 解答 直接用辛普森公式积分 ∫baf(x)×dx≈b−a6[f(a)+f(a+b2)+f(b)] \int_a^bf(x)\times dx \approx ...

  2. [BZOJ 1500] [NOI2005] 维修数列

    题目链接:BZOJ - 1500 题目分析 我要先说一下,这道题我写了一晚上,然后Debug了一整个白天..........再一次被自己的蒟蒻程度震惊= = 这道题是传说中的Splay维护数列的Bos ...

  3. BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay)

    BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay) 手动博客搬家: 本文发表于20180825 00:34:49, 原地址https://blog.csdn.ne ...

  4. [BZOJ1500][NOI2005]维修数列(splay)

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 16266  Solved: 5410 [Submit][Sta ...

  5. NOI 2005 题解

    维修数列 (传送门) 题意 对于一个数列,支持插入,删除,修改,翻转,求和,求最大子列的操作 分析 又是对于一个数列的各种操作,考察splay的各种操作(NOI这几年真爱考splay),没什么好分析的 ...

  6. 【BZOJ1500】[NOI2005]维修数列 Splay

    [BZOJ1500][NOI2005]维修数列 Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目. 第2 ...

  7. 数据结构之fhq-treap——Chef and Sets,[HNOI2012]永无乡,Play with Chain,[NOI2005]维修数列(结构体版代码)

    因为非常板,所以主要是代码 Tyvj 1728 普通平衡树 Chef and Sets [HNOI2012]永无乡 Play with Chain [NOI2005]维修数列 题目很水,所以可能会出现 ...

  8. BZOJ 1500 维修数列

    Splay序列操作的大模板题 这个真的是噩梦..调了整整一个晚上,可以说完全被榨干了orz.. 因为我的splay写的实在是太丑了,手动加的哨兵节点,开头忘记pushup了,找了一晚上才找到... 还 ...

  9. 1500: [NOI2005]维修数列 (Splay)

    1W1A(inf开太大) #include<algorithm> #include<iostream> #include<cstring> #include< ...

最新文章

  1. 多重比对序列的格式及其应用
  2. MySQL修改数据库:ALTER DATABASE用法简介
  3. 【SICP练习】144 练习3.82
  4. GPU编程与CG语言之阳春白雪下里巴人 读书笔记
  5. 当我们在谈论HTTP缓存时我们在谈论什么
  6. java-web前端 javascript
  7. iOS iPhone官方参考资料明细
  8. shiro-cas------整合springboot客户端
  9. Java通过微信公众号获取地理位置信息
  10. 临近毕业,查降重来了
  11. 【Ubuntu版】CMake安装教程
  12. 利用python中的pygame模块开发fc坦克大战(可自定义地图,包括部分素材)
  13. suse 12 sp5安装bug
  14. 5G基站:宏基站微基站皮基站飞基站
  15. 软件开发中的时区问题
  16. 打开组策略 计算机配置,组策略怎么打开? 打开组策略命令与4种方法-电脑教程...
  17. Python3,4行代码给图片加美颜,拍照再也不需要开美颜滤镜了。
  18. 前端生成二维码图片以及条形码图片
  19. 深度终端:ubuntu等linux下好用的远程终端软件
  20. 十二月,我们一起在云台山风景区赏雪

热门文章

  1. 史上最全的JFinal源码分析(不间断更新)
  2. Android源码和内核源码的下载,编译和执行
  3. Python基本语法[二],python入门到精通[四] (转)
  4. 常用T-Code总结
  5. 福师离线 微型计算机与外部,福师《计算机应用基础》离线作业答案
  6. franz ubuntu_重新审视Unix理念,持续测试,Franz,Gitbase,Python,Linux等
  7. 我的新LulzBot Mini 3D打印机入门
  8. (42)Gulp在Yeoman脚手架工具中的应用
  9. ES6(ECMAScript2015)/01/ES6简介
  10. 前端:JS/29/实例:控制div显示_滚动的图片