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\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] 维修数列相关推荐
- BZOJ 1502 NOI 2005 月下柠檬树
题目大意 给定一些圆和梯形,求它们面积的并 解答 直接用辛普森公式积分 ∫baf(x)×dx≈b−a6[f(a)+f(a+b2)+f(b)] \int_a^bf(x)\times dx \approx ...
- [BZOJ 1500] [NOI2005] 维修数列
题目链接:BZOJ - 1500 题目分析 我要先说一下,这道题我写了一晚上,然后Debug了一整个白天..........再一次被自己的蒟蒻程度震惊= = 这道题是传说中的Splay维护数列的Bos ...
- BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay)
BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay) 手动博客搬家: 本文发表于20180825 00:34:49, 原地址https://blog.csdn.ne ...
- [BZOJ1500][NOI2005]维修数列(splay)
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 16266 Solved: 5410 [Submit][Sta ...
- NOI 2005 题解
维修数列 (传送门) 题意 对于一个数列,支持插入,删除,修改,翻转,求和,求最大子列的操作 分析 又是对于一个数列的各种操作,考察splay的各种操作(NOI这几年真爱考splay),没什么好分析的 ...
- 【BZOJ1500】[NOI2005]维修数列 Splay
[BZOJ1500][NOI2005]维修数列 Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目. 第2 ...
- 数据结构之fhq-treap——Chef and Sets,[HNOI2012]永无乡,Play with Chain,[NOI2005]维修数列(结构体版代码)
因为非常板,所以主要是代码 Tyvj 1728 普通平衡树 Chef and Sets [HNOI2012]永无乡 Play with Chain [NOI2005]维修数列 题目很水,所以可能会出现 ...
- BZOJ 1500 维修数列
Splay序列操作的大模板题 这个真的是噩梦..调了整整一个晚上,可以说完全被榨干了orz.. 因为我的splay写的实在是太丑了,手动加的哨兵节点,开头忘记pushup了,找了一晚上才找到... 还 ...
- 1500: [NOI2005]维修数列 (Splay)
1W1A(inf开太大) #include<algorithm> #include<iostream> #include<cstring> #include< ...
最新文章
- 多重比对序列的格式及其应用
- MySQL修改数据库:ALTER DATABASE用法简介
- 【SICP练习】144 练习3.82
- GPU编程与CG语言之阳春白雪下里巴人 读书笔记
- 当我们在谈论HTTP缓存时我们在谈论什么
- java-web前端 javascript
- iOS iPhone官方参考资料明细
- shiro-cas------整合springboot客户端
- Java通过微信公众号获取地理位置信息
- 临近毕业,查降重来了
- 【Ubuntu版】CMake安装教程
- 利用python中的pygame模块开发fc坦克大战(可自定义地图,包括部分素材)
- suse 12 sp5安装bug
- 5G基站:宏基站微基站皮基站飞基站
- 软件开发中的时区问题
- 打开组策略 计算机配置,组策略怎么打开? 打开组策略命令与4种方法-电脑教程...
- Python3,4行代码给图片加美颜,拍照再也不需要开美颜滤镜了。
- 前端生成二维码图片以及条形码图片
- 深度终端:ubuntu等linux下好用的远程终端软件
- 十二月,我们一起在云台山风景区赏雪
热门文章
- 史上最全的JFinal源码分析(不间断更新)
- Android源码和内核源码的下载,编译和执行
- Python基本语法[二],python入门到精通[四] (转)
- 常用T-Code总结
- 福师离线 微型计算机与外部,福师《计算机应用基础》离线作业答案
- franz ubuntu_重新审视Unix理念,持续测试,Franz,Gitbase,Python,Linux等
- 我的新LulzBot Mini 3D打印机入门
- (42)Gulp在Yeoman脚手架工具中的应用
- ES6(ECMAScript2015)/01/ES6简介
- 前端:JS/29/实例:控制div显示_滚动的图片