题意:实现一种数据结构,支持对一个数列的 6 种操作:
第 x 个数到第 y 个数之间的数每个加 D;
第 x 个数到第 y 个数之间全部数翻转;
第 x 个数到第 y 个数之间的数,向后循环流动 c 次,即后面 c个数变成这段子序列的最前面 c 个,前面的被挤到后面。
在第 x 个数后面插入一个数 P。
删除第 x 个数。
求第 x 个数到第 y 个数之间的最小数字。

题解:

(待补)

代码先放上:

(是真的长啊,我已经是比较压行的选手了,依然写了230行)

1.利用stack回收内存池

  1. #include <cstdio>
  2. #include <stack>
  3. #include <cstring>
  4. #include <vector>
  5. #define ll long long
  6. #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
  7. using namespace std;
  8. const int maxn=1e6+10,maxm=2e6+10;
  9. const int INF=0x3f3f3f3f;
  10. class splaytree{
  11. public:
  12. struct splaynode{
  13. splaynode *son[2],*pre;
  14. ll val,tag,mn;
  15. int size,rev;
  16. void init(ll x){
  17. pre=son[1]=son[0]=NULL;
  18. mn=val=x;
  19. tag=rev=0;
  20. size=1;
  21. }
  22. void add(ll x){tag+=x,mn+=x;}
  23. };
  24. typedef struct splaynode* nodep;
  25. int cnt;
  26. stack<nodep> stk;
  27. nodep root;
  28. vector<splaynode> node;
  29. int getsize(nodep x){return x?x->size:0;}
  30. void pushdown(nodep now){
  31. if(!now) return ;
  32. if(now->tag){
  33. ll tag=now->tag;
  34. now->val+=tag;
  35. if(now->son[0]) now->son[0]->add(tag);
  36. if(now->son[1]) now->son[1]->add(tag);
  37. now->tag=0;
  38. }
  39. if(now->rev){
  40. swap(now->son[0],now->son[1]);
  41. now->rev=0;
  42. if(now->son[0]) now->son[0]->rev^=1;
  43. if(now->son[1]) now->son[1]->rev^=1;
  44. }
  45. }
  46. void pushup(nodep now){
  47. if(!now) return ;
  48. now->size=1,now->mn=now->val;
  49. if(now->son[0]) {
  50. now->mn=min(now->mn,now->son[0]->mn);
  51. now->size+=now->son[0]->size;
  52. }
  53. if(now->son[1]){
  54. now->mn=min(now->mn,now->son[1]->mn);
  55. now->size+=now->son[1]->size;
  56. }
  57. }
  58. void rotate(nodep now,int d){
  59. nodep fa=now->pre;
  60. pushdown(fa);
  61. pushdown(now);
  62. pushdown(now->son[d]);
  63. fa->son[!d]=now->son[d];
  64. if(now->son[d]) now->son[d]->pre=fa;
  65. now->pre=fa->pre;
  66. if(fa->pre){
  67. if(fa->pre->son[0]==fa) fa->pre->son[0]=now;
  68. else fa->pre->son[1]=now;
  69. }else root=now;
  70. now->son[d]=fa;
  71. fa->pre=now;
  72. pushup(fa);
  73. }
  74. void splay(nodep now,nodep dst){
  75. pushdown(now);
  76. while(now!=dst){
  77. if(now->pre==dst){
  78. if(dst->son[0]==now) rotate(now,1);
  79. else rotate(now,0);
  80. break;
  81. }
  82. nodep fa=now->pre,gfa=fa->pre;
  83. if(gfa->son[0]==fa){
  84. if(fa->son[0]==now) {rotate(fa,1);rotate(now,1);}
  85. else {rotate(now,0);rotate(now,1);}
  86. }else {
  87. if(fa->son[1]==now) {rotate(fa,0);rotate(now,0);}
  88. else {rotate(now,1);rotate(now,0);}
  89. }
  90. if(gfa==dst) break;
  91. pushup(now);
  92. }
  93. pushup(now);
  94. }
  95. void find(int k,nodep fa){
  96. int tmp;
  97. nodep t=root;
  98. while (1) {
  99. pushdown(t);
  100. tmp=getsize(t->son[0]);
  101. if (k==tmp+1) break;
  102. if (k<=tmp) t=t->son[0];
  103. else {
  104. k-=tmp+1,t=t->son[1];
  105. }
  106. }
  107. pushdown(t);
  108. splay(t, fa);
  109. }
  110. void findseg(int s,int t){
  111. find(s,root);
  112. find(t+2,root->son[1]);
  113. }
  114. void insert(int pos,ll val){
  115. findseg(pos+1,pos);
  116. nodep now,fa=root->son[1];
  117. pushdown(root);
  118. pushdown(fa);
  119. if(!stk.empty()){
  120. now=stk.top();
  121. stk.pop();
  122. }else now=&node[cnt++];
  123. now->init(val);
  124. now->son[1]=fa;
  125. fa->pre=now;
  126. root->son[1]=now;
  127. now->pre=root;
  128. splay(fa,root);
  129. }
  130. void add(int s,int t,ll val){
  131. findseg(s,t);
  132. nodep now = root->son[1]->son[0];
  133. pushdown(now);
  134. pushup(now);
  135. now->mn+=val;
  136. now->tag+=val;
  137. splay(now,root);
  138. }
  139. void reverse(int s,int t){
  140. findseg(s,t);
  141. root->son[1]->son[0]->rev^=1;
  142. nodep now=root->son[1]->son[0];
  143. splay(now,root);
  144. }
  145. void revolve(int s,int t,int len){
  146. nodep x,y;
  147. findseg(s,t);
  148. find(t+1-len,root->son[1]->son[0]);
  149. x=root->son[1]->son[0];
  150. pushdown(x);
  151. y=x->son[1];
  152. x->son[1]=NULL;
  153. find(s+1,root->son[1]->son[0]);
  154. x=root->son[1]->son[0];
  155. pushdown(x);
  156. x->son[0]=y;
  157. y->pre=x;
  158. splay(y,root);
  159. }
  160. ll getmin(int s,int t) {
  161. findseg(s,t);
  162. nodep now=root->son[1];
  163. pushdown(now);
  164. now=now->son[0];
  165. pushdown(now);
  166. pushup(now);
  167. return now->mn;
  168. }
  169. void erase(int pos){
  170. findseg(pos, pos);
  171. pushdown(root->son[1]);
  172. stk.push(root->son[1]->son[0]);
  173. root->son[1]->son[0] = NULL;
  174. nodep now = root->son[1];
  175. splay(now,root);
  176. }
  177. splaytree(ll*a,int n){
  178. cnt=0;
  179. node.resize(maxn);
  180. root=&node[cnt++];
  181. root->init(INF);
  182. root->son[1]=&node[cnt++];
  183. root->son[1]->init(INF);
  184. while (!stk.empty()) stk.pop();
  185. rep(i,0,n-1) insert(i, a[i]);
  186. }
  187. };
  188.  
  189. ll v[maxn];
  190. int main() {
  191. int n, m;
  192. scanf("%d", &n);
  193. rep(i,0,n-1) scanf("%lld",&v[i]);
  194. scanf("%d", &m);
  195. splaytree tree(v, n);
  196. while (m--) {
  197. char s[50];
  198. scanf("%s",s);
  199. if (s[0]=='A') {
  200. int l, r, d;
  201. scanf("%d%d%d",&l,&r,&d);
  202. tree.add(l,r,d);
  203. }
  204. if (s[0]=='R') {
  205. int l, r;
  206. scanf("%d%d",&l,&r);
  207. if (s[3]=='E') tree.reverse(l,r);
  208. else {
  209. int k;
  210. scanf("%d",&k);
  211. int tn=r-l+1;
  212. k=(k%tn+tn)%tn;
  213. if (l==r||k==0) continue;
  214. tree.revolve(l,r,k);
  215. }
  216. }
  217. if (s[0]=='I') {
  218. int x, d;
  219. scanf("%d%d",&x,&d);
  220. tree.insert(x,d);
  221. }
  222. if (s[0]=='D') {
  223. int x;
  224. scanf("%d",&x);
  225. tree.erase(x);
  226. }
  227. if (s[0]=='M') {
  228. int l, r;
  229. scanf("%d%d",&l,&r);
  230. printf("%lld\n",tree.getmin(l,r));
  231. }
  232. }
  233. return 0;
  234. }

2.不用stack

  1. #include <iostream>
  2. #include <vector>
  3. #define ll long long
  4. #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
  5. using namespace std;
  6. const int maxn=1e6+10,maxm=2e6+10;
  7. const int INF=0x3f3f3f3f;
  8. class splaytree{
  9. public:
  10. struct splaynode{
  11. splaynode *son[2],*pre;
  12. ll val,tag,mn;
  13. int size,rev;
  14. void init(ll x){
  15. pre=son[1]=son[0]=NULL;
  16. mn=val=x;
  17. tag=rev=0;
  18. size=1;
  19. }
  20. void add(ll x){tag+=x,mn+=x;}
  21. };
  22. typedef struct splaynode* nodep;
  23. int cnt;
  24. nodep root;
  25. vector<splaynode> node;
  26. int getsize(nodep x){return x?x->size:0;}
  27. void pushdown(nodep now){
  28. if(!now) return ;
  29. if(now->tag){
  30. ll tag=now->tag;
  31. now->val+=tag;
  32. if(now->son[0]) now->son[0]->add(tag);
  33. if(now->son[1]) now->son[1]->add(tag);
  34. now->tag=0;
  35. }
  36. if(now->rev){
  37. swap(now->son[0],now->son[1]);
  38. now->rev=0;
  39. if(now->son[0]) now->son[0]->rev^=1;
  40. if(now->son[1]) now->son[1]->rev^=1;
  41. }
  42. }
  43. void pushup(nodep now){
  44. if(!now) return ;
  45. now->size=1,now->mn=now->val;
  46. if(now->son[0]) {
  47. now->mn=min(now->mn,now->son[0]->mn);
  48. now->size+=now->son[0]->size;
  49. }
  50. if(now->son[1]){
  51. now->mn=min(now->mn,now->son[1]->mn);
  52. now->size+=now->son[1]->size;
  53. }
  54. }
  55. void rotate(nodep now,int d){
  56. nodep fa=now->pre;
  57. pushdown(fa);
  58. pushdown(now);
  59. pushdown(now->son[d]);
  60. fa->son[!d]=now->son[d];
  61. if(now->son[d]) now->son[d]->pre=fa;
  62. now->pre=fa->pre;
  63. if(fa->pre){
  64. if(fa->pre->son[0]==fa) fa->pre->son[0]=now;
  65. else fa->pre->son[1]=now;
  66. }else root=now;
  67. now->son[d]=fa;
  68. fa->pre=now;
  69. pushup(fa);
  70. }
  71. void splay(nodep now,nodep dst){
  72. pushdown(now);
  73. while(now!=dst){
  74. if(now->pre==dst){
  75. if(dst->son[0]==now) rotate(now,1);
  76. else rotate(now,0);
  77. break;
  78. }
  79. nodep fa=now->pre,gfa=fa->pre;
  80. if(gfa->son[0]==fa){
  81. if(fa->son[0]==now) {rotate(fa,1);rotate(now,1);}
  82. else {rotate(now,0);rotate(now,1);}
  83. }else {
  84. if(fa->son[1]==now) {rotate(fa,0);rotate(now,0);}
  85. else {rotate(now,1);rotate(now,0);}
  86. }
  87. if(gfa==dst) break;
  88. pushup(now);
  89. }
  90. pushup(now);
  91. }
  92. void find(int k,nodep fa){
  93. int tmp;
  94. nodep t=root;
  95. while (1) {
  96. pushdown(t);
  97. tmp=getsize(t->son[0]);
  98. if (k==tmp+1) break;
  99. if (k<=tmp) t=t->son[0];
  100. else {
  101. k-=tmp+1,t=t->son[1];
  102. }
  103. }
  104. pushdown(t);
  105. splay(t, fa);
  106. }
  107. void findseg(int s,int t){
  108. find(s,root);
  109. find(t+2,root->son[1]);
  110. }
  111. void insert(int pos,ll val){
  112. findseg(pos+1,pos);
  113. nodep now,fa=root->son[1];
  114. pushdown(root);
  115. pushdown(fa);
  116. now=&node[cnt++];
  117. now->init(val);
  118. now->son[1]=fa;
  119. fa->pre=now;
  120. root->son[1]=now;
  121. now->pre=root;
  122. splay(fa,root);
  123. }
  124. void add(int s,int t,ll val){
  125. findseg(s,t);
  126. nodep now = root->son[1]->son[0];
  127. pushdown(now);
  128. pushup(now);
  129. now->mn+=val;
  130. now->tag+=val;
  131. splay(now,root);
  132. }
  133. void reverse(int s,int t){
  134. findseg(s,t);
  135. root->son[1]->son[0]->rev^=1;
  136. nodep now=root->son[1]->son[0];
  137. splay(now,root);
  138. }
  139. void revolve(int s,int t,int len){
  140. nodep x,y;
  141. findseg(s,t);
  142. find(t+1-len,root->son[1]->son[0]);
  143. x=root->son[1]->son[0];
  144. pushdown(x);
  145. y=x->son[1];
  146. x->son[1]=NULL;
  147. find(s+1,root->son[1]->son[0]);
  148. x=root->son[1]->son[0];
  149. pushdown(x);
  150. x->son[0]=y;
  151. y->pre=x;
  152. splay(y,root);
  153. }
  154. ll getmin(int s,int t) {
  155. findseg(s,t);
  156. nodep now=root->son[1];
  157. pushdown(now);
  158. now=now->son[0];
  159. pushdown(now);
  160. pushup(now);
  161. return now->mn;
  162. }
  163. void erase(int pos){
  164. findseg(pos, pos);
  165. pushdown(root->son[1]);
  166. root->son[1]->son[0] = NULL;
  167. nodep now = root->son[1];
  168. splay(now,root);
  169. }
  170. splaytree(vector<int> num,int n){
  171. cnt=0;
  172. node.resize(n+7);
  173. root=&node[cnt++];
  174. root->init(INF);
  175. root->son[1]=&node[cnt++];
  176. root->son[1]->init(INF);
  177. int size=num.size();
  178. rep(i,0,size-1) insert(i, num[i]);
  179. }
  180. };
  181. int main() {
  182. ios::sync_with_stdio(false),cin.tie(0);
  183. int n,m;
  184. cin>>n;
  185. vector<int> v(n);
  186. rep(i,0,n-1) cin>>v[i];
  187. cin>>m;
  188. splaytree tree(v,n+m);
  189. while (m--) {
  190. string s;
  191. cin>>s;
  192. if (s[0]=='A') {
  193. int l,r,d;cin>>l>>r>>d;
  194. tree.add(l,r,d);
  195. }
  196. if (s[0]=='R') {
  197. int l,r;cin>>l>>r;
  198. if (s[3]=='E') tree.reverse(l,r);
  199. else {
  200. int k;cin>>k;
  201. int tn=r-l+1;
  202. k=(k%tn+tn)%tn;
  203. if (l==r||k==0) continue;
  204. tree.revolve(l,r,k);
  205. }
  206. }
  207. if (s[0]=='I') {
  208. int x,d;cin>>x>>d;
  209. tree.insert(x,d);
  210. }
  211. if (s[0]=='D') {
  212. int x;cin>>x;
  213. tree.erase(x);
  214. }
  215. if (s[0]=='M') {
  216. int l,r;cin>>l>>r;
  217. cout<<tree.getmin(l,r)<<endl;
  218. }
  219. }
  220. return 0;
  221. }

  

POJ3580 SuperMemo splay伸展树,区间操作的更多相关文章

  1. 2018牛客网暑期ACM多校训练营(第三场) H - Shuffle Cards - [splay伸展树][区间移动][区间反转]

    题目链接:https://www.nowcoder.com/acm/contest/141/C 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K ...

  2. Splay伸展树学习笔记

    Splay伸展树 有篇Splay入门必看文章 —— CSDN链接 经典引文 空间效率:O(n) 时间效率:O(log n)插入.查找.删除 创造者:Daniel Sleator 和 Robert Ta ...

  3. 【学时总结】◆学时·VI◆ SPLAY伸展树

    ◆学时·VI◆ SPLAY伸展树 平衡树之多,学之不尽也…… ◇算法概述 二叉排序树的一种,自动平衡,由 Tarjan 提出并实现.得名于特有的 Splay 操作. Splay操作:将节点u通过单旋. ...

  4. Splay伸展树入门(单点操作,区间维护)附例题模板

    Pps:终于学会了伸展树的区间操作,做一个完整的总结,总结一下自己的伸展树的单点操作和区间维护,顺便给未来的自己总结复习用. splay是一种平衡树,[平均]操作复杂度O(nlogn).首先平衡树先是 ...

  5. [置顶] hdu 1890 伸展树区间翻转

    题意: 给你n个数,每次先输出第i大的数的位置(如果有多个,选下标小的那个),然后每次将第i个位置到第i大的数所在位置之间的数进行翻转. 思路:输入的数组可能有多个相同的值,我们可以进行两次排序把数组 ...

  6. [Splay伸展树]splay树入门级教程

    首先声明,本教程的对象是完全没有接触过splay的OIer,大牛请右上角.. 首先引入一下splay的概念,他的中文名是伸展树,意思差不多就是可以随意翻转的二叉树 PS:百度百科中伸展树读作:BoGa ...

  7. [算法] 数据结构 splay(伸展树)解析

    前言 splay学了已经很久了,只不过一直没有总结,鸽了好久来写一篇总结. 先介绍 splay:亦称伸展树,为二叉搜索树的一种,部分操作能在 \(O( \log n)\) 内完成,如插入.查找.删除. ...

  8. Splay 伸展树

    废话不说,有篇论文可供参考:杨思雨:<伸展树的基本操作与应用> Splay的好处可以快速分裂和合并. ===============================14.07.26更新== ...

  9. UVA 11922 Permutation Transformer —— splay伸展树

    题意:根据m条指令改变排列1 2 3 4 … n ,每条指令(a, b)表示取出第a~b个元素,反转后添加到排列尾部 分析:用一个可分裂合并的序列来表示整个序列,截取一段可以用两次分裂一次合并实现,粘 ...

随机推荐

  1. UDP协议

    本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明出处http://blog.csdn.net/yming0221/article/details/7532512 更多请看专栏, ...

  2. Elasticsearch 集群 单服务器 超级详细教程

    前言 之前了解了Elasticsearch的基本概念.将spring boot + ElasticSearch + head插件 搞通之后.紧接着对es进行下一步的探索:集群.查阅资料的过程中,找到了 ...

  3. log 的 debug()、 error()、 info()方法

    log4j定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从高到低依次为:OFF.FATAL.ERROR.WARN.INFO.DEBUG.TRACE. ALL. 简单的说,就是 ...

  4. 从零开始搭建高性能高可用Tomcat服务器

    目标: Tomcat+Nginx+Memcached Ubuntu 16.04 64位测试通过 动静分类.负载均衡.集群.Javolution序列化.高性能.高可用 配置环境(目前均为最新稳定版): ...

  5. ArcGis Python脚本——批量添加字段

    先看如何增加一个字段 函数:arcpy.AddField_management 语法:AddFields_management (in_table, field_description) 参数 说明 ...

  6. [Android] Android 异步定时任务实现的三种方法(以SeekBar的进度自动实现为例)

    [Android] Android 定时异步任务实现的三种方法(以SeekBar的进度自动实现为例) 一.采用Handler与线程的sleep(long)方法 二.采用Handler与timer及Ti ...

  7. jsp过滤器

    1.ip过滤 IpFilter: package com.cn.filter; import java.io.IOException; import javax.servlet.Filter; imp ...

  8. 账号管理文件/etc/passwd和/etc/shadow

    /etc/passwd和/etc/shadow是Linux中两个账号管理的重要文件 一./etc/passwd        这个文件中每一行代表一个账号,有几行就代表系统中存在几个账号.有些账号是系 ...

  9. springboot13 发布和监听事件

    spring中的事件驱动模型Event(也叫发布订阅模式),是观察者模式的一个典型的应用 好处:业务解耦,在不影响原来业务逻辑的情况下,加入其它业务 场景: app上线后已实现用户注册功能,现需要在用 ...

  10. Docker(二)搭建和使用Docker

    摘自 https://mp.weixin.qq.com/s/E9tqhe00EjfV8y1pqWkZfw 一.Docker的架构 Docker使用C/S结构,即客户端/服务器体系结构.Docker客户 ...