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

题解:

(待补)

代码先放上:

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

1.利用stack回收内存池

#include <cstdio>
#include <stack>
#include <cstring>
#include <vector>
#define ll long long
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
const int maxn=1e6+10,maxm=2e6+10;
const int INF=0x3f3f3f3f;
class splaytree{
public:
struct splaynode{
splaynode *son[2],*pre;
ll val,tag,mn;
int size,rev;
void init(ll x){
pre=son[1]=son[0]=NULL;
mn=val=x;
tag=rev=0;
size=1;
}
void add(ll x){tag+=x,mn+=x;}
};
typedef struct splaynode* nodep;
int cnt;
stack<nodep> stk;
nodep root;
vector<splaynode> node;
int getsize(nodep x){return x?x->size:0;}
void pushdown(nodep now){
if(!now) return ;
if(now->tag){
ll tag=now->tag;
now->val+=tag;
if(now->son[0]) now->son[0]->add(tag);
if(now->son[1]) now->son[1]->add(tag);
now->tag=0;
}
if(now->rev){
swap(now->son[0],now->son[1]);
now->rev=0;
if(now->son[0]) now->son[0]->rev^=1;
if(now->son[1]) now->son[1]->rev^=1;
}
}
void pushup(nodep now){
if(!now) return ;
now->size=1,now->mn=now->val;
if(now->son[0]) {
now->mn=min(now->mn,now->son[0]->mn);
now->size+=now->son[0]->size;
}
if(now->son[1]){
now->mn=min(now->mn,now->son[1]->mn);
now->size+=now->son[1]->size;
}
}
void rotate(nodep now,int d){
nodep fa=now->pre;
pushdown(fa);
pushdown(now);
pushdown(now->son[d]);
fa->son[!d]=now->son[d];
if(now->son[d]) now->son[d]->pre=fa;
now->pre=fa->pre;
if(fa->pre){
if(fa->pre->son[0]==fa) fa->pre->son[0]=now;
else fa->pre->son[1]=now;
}else root=now;
now->son[d]=fa;
fa->pre=now;
pushup(fa);
}
void splay(nodep now,nodep dst){
pushdown(now);
while(now!=dst){
if(now->pre==dst){
if(dst->son[0]==now) rotate(now,1);
else rotate(now,0);
break;
}
nodep fa=now->pre,gfa=fa->pre;
if(gfa->son[0]==fa){
if(fa->son[0]==now) {rotate(fa,1);rotate(now,1);}
else {rotate(now,0);rotate(now,1);}
}else {
if(fa->son[1]==now) {rotate(fa,0);rotate(now,0);}
else {rotate(now,1);rotate(now,0);}
}
if(gfa==dst) break;
pushup(now);
}
pushup(now);
}
void find(int k,nodep fa){
int tmp;
nodep t=root;
while (1) {
pushdown(t);
tmp=getsize(t->son[0]);
if (k==tmp+1) break;
if (k<=tmp) t=t->son[0];
else {
k-=tmp+1,t=t->son[1];
}
}
pushdown(t);
splay(t, fa);
}
void findseg(int s,int t){
find(s,root);
find(t+2,root->son[1]);
}
void insert(int pos,ll val){
findseg(pos+1,pos);
nodep now,fa=root->son[1];
pushdown(root);
pushdown(fa);
if(!stk.empty()){
now=stk.top();
stk.pop();
}else now=&node[cnt++];
now->init(val);
now->son[1]=fa;
fa->pre=now;
root->son[1]=now;
now->pre=root;
splay(fa,root);
}
void add(int s,int t,ll val){
findseg(s,t);
nodep now = root->son[1]->son[0];
pushdown(now);
pushup(now);
now->mn+=val;
now->tag+=val;
splay(now,root);
}
void reverse(int s,int t){
findseg(s,t);
root->son[1]->son[0]->rev^=1;
nodep now=root->son[1]->son[0];
splay(now,root);
}
void revolve(int s,int t,int len){
nodep x,y;
findseg(s,t);
find(t+1-len,root->son[1]->son[0]);
x=root->son[1]->son[0];
pushdown(x);
y=x->son[1];
x->son[1]=NULL;
find(s+1,root->son[1]->son[0]);
x=root->son[1]->son[0];
pushdown(x);
x->son[0]=y;
y->pre=x;
splay(y,root);
}
ll getmin(int s,int t) {
findseg(s,t);
nodep now=root->son[1];
pushdown(now);
now=now->son[0];
pushdown(now);
pushup(now);
return now->mn;
}
void erase(int pos){
findseg(pos, pos);
pushdown(root->son[1]);
stk.push(root->son[1]->son[0]);
root->son[1]->son[0] = NULL;
nodep now = root->son[1];
splay(now,root);
}
splaytree(ll*a,int n){
cnt=0;
node.resize(maxn);
root=&node[cnt++];
root->init(INF);
root->son[1]=&node[cnt++];
root->son[1]->init(INF);
while (!stk.empty()) stk.pop();
rep(i,0,n-1) insert(i, a[i]);
}
}; ll v[maxn];
int main() {
int n, m;
scanf("%d", &n);
rep(i,0,n-1) scanf("%lld",&v[i]);
scanf("%d", &m);
splaytree tree(v, n);
while (m--) {
char s[50];
scanf("%s",s);
if (s[0]=='A') {
int l, r, d;
scanf("%d%d%d",&l,&r,&d);
tree.add(l,r,d);
}
if (s[0]=='R') {
int l, r;
scanf("%d%d",&l,&r);
if (s[3]=='E') tree.reverse(l,r);
else {
int k;
scanf("%d",&k);
int tn=r-l+1;
k=(k%tn+tn)%tn;
if (l==r||k==0) continue;
tree.revolve(l,r,k);
}
}
if (s[0]=='I') {
int x, d;
scanf("%d%d",&x,&d);
tree.insert(x,d);
}
if (s[0]=='D') {
int x;
scanf("%d",&x);
tree.erase(x);
}
if (s[0]=='M') {
int l, r;
scanf("%d%d",&l,&r);
printf("%lld\n",tree.getmin(l,r));
}
}
return 0;
}

2.不用stack

#include <iostream>
#include <vector>
#define ll long long
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
const int maxn=1e6+10,maxm=2e6+10;
const int INF=0x3f3f3f3f;
class splaytree{
public:
struct splaynode{
splaynode *son[2],*pre;
ll val,tag,mn;
int size,rev;
void init(ll x){
pre=son[1]=son[0]=NULL;
mn=val=x;
tag=rev=0;
size=1;
}
void add(ll x){tag+=x,mn+=x;}
};
typedef struct splaynode* nodep;
int cnt;
nodep root;
vector<splaynode> node;
int getsize(nodep x){return x?x->size:0;}
void pushdown(nodep now){
if(!now) return ;
if(now->tag){
ll tag=now->tag;
now->val+=tag;
if(now->son[0]) now->son[0]->add(tag);
if(now->son[1]) now->son[1]->add(tag);
now->tag=0;
}
if(now->rev){
swap(now->son[0],now->son[1]);
now->rev=0;
if(now->son[0]) now->son[0]->rev^=1;
if(now->son[1]) now->son[1]->rev^=1;
}
}
void pushup(nodep now){
if(!now) return ;
now->size=1,now->mn=now->val;
if(now->son[0]) {
now->mn=min(now->mn,now->son[0]->mn);
now->size+=now->son[0]->size;
}
if(now->son[1]){
now->mn=min(now->mn,now->son[1]->mn);
now->size+=now->son[1]->size;
}
}
void rotate(nodep now,int d){
nodep fa=now->pre;
pushdown(fa);
pushdown(now);
pushdown(now->son[d]);
fa->son[!d]=now->son[d];
if(now->son[d]) now->son[d]->pre=fa;
now->pre=fa->pre;
if(fa->pre){
if(fa->pre->son[0]==fa) fa->pre->son[0]=now;
else fa->pre->son[1]=now;
}else root=now;
now->son[d]=fa;
fa->pre=now;
pushup(fa);
}
void splay(nodep now,nodep dst){
pushdown(now);
while(now!=dst){
if(now->pre==dst){
if(dst->son[0]==now) rotate(now,1);
else rotate(now,0);
break;
}
nodep fa=now->pre,gfa=fa->pre;
if(gfa->son[0]==fa){
if(fa->son[0]==now) {rotate(fa,1);rotate(now,1);}
else {rotate(now,0);rotate(now,1);}
}else {
if(fa->son[1]==now) {rotate(fa,0);rotate(now,0);}
else {rotate(now,1);rotate(now,0);}
}
if(gfa==dst) break;
pushup(now);
}
pushup(now);
}
void find(int k,nodep fa){
int tmp;
nodep t=root;
while (1) {
pushdown(t);
tmp=getsize(t->son[0]);
if (k==tmp+1) break;
if (k<=tmp) t=t->son[0];
else {
k-=tmp+1,t=t->son[1];
}
}
pushdown(t);
splay(t, fa);
}
void findseg(int s,int t){
find(s,root);
find(t+2,root->son[1]);
}
void insert(int pos,ll val){
findseg(pos+1,pos);
nodep now,fa=root->son[1];
pushdown(root);
pushdown(fa);
now=&node[cnt++];
now->init(val);
now->son[1]=fa;
fa->pre=now;
root->son[1]=now;
now->pre=root;
splay(fa,root);
}
void add(int s,int t,ll val){
findseg(s,t);
nodep now = root->son[1]->son[0];
pushdown(now);
pushup(now);
now->mn+=val;
now->tag+=val;
splay(now,root);
}
void reverse(int s,int t){
findseg(s,t);
root->son[1]->son[0]->rev^=1;
nodep now=root->son[1]->son[0];
splay(now,root);
}
void revolve(int s,int t,int len){
nodep x,y;
findseg(s,t);
find(t+1-len,root->son[1]->son[0]);
x=root->son[1]->son[0];
pushdown(x);
y=x->son[1];
x->son[1]=NULL;
find(s+1,root->son[1]->son[0]);
x=root->son[1]->son[0];
pushdown(x);
x->son[0]=y;
y->pre=x;
splay(y,root);
}
ll getmin(int s,int t) {
findseg(s,t);
nodep now=root->son[1];
pushdown(now);
now=now->son[0];
pushdown(now);
pushup(now);
return now->mn;
}
void erase(int pos){
findseg(pos, pos);
pushdown(root->son[1]);
root->son[1]->son[0] = NULL;
nodep now = root->son[1];
splay(now,root);
}
splaytree(vector<int> num,int n){
cnt=0;
node.resize(n+7);
root=&node[cnt++];
root->init(INF);
root->son[1]=&node[cnt++];
root->son[1]->init(INF);
int size=num.size();
rep(i,0,size-1) insert(i, num[i]);
}
};
int main() {
ios::sync_with_stdio(false),cin.tie(0);
int n,m;
cin>>n;
vector<int> v(n);
rep(i,0,n-1) cin>>v[i];
cin>>m;
splaytree tree(v,n+m);
while (m--) {
string s;
cin>>s;
if (s[0]=='A') {
int l,r,d;cin>>l>>r>>d;
tree.add(l,r,d);
}
if (s[0]=='R') {
int l,r;cin>>l>>r;
if (s[3]=='E') tree.reverse(l,r);
else {
int k;cin>>k;
int tn=r-l+1;
k=(k%tn+tn)%tn;
if (l==r||k==0) continue;
tree.revolve(l,r,k);
}
}
if (s[0]=='I') {
int x,d;cin>>x>>d;
tree.insert(x,d);
}
if (s[0]=='D') {
int x;cin>>x;
tree.erase(x);
}
if (s[0]=='M') {
int l,r;cin>>l>>r;
cout<<tree.getmin(l,r)<<endl;
}
}
return 0;
}

  

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. Kafka技术内幕 读书笔记之(五) 协调者——消费者加入消费组

    消费者客户端轮询的3个步骤:发送拉取请求,客户端轮询,获取拉取结果 . 消费者在发送拉取请求之前,必须首先满足下面的两个条件.- 确保消费者已经连接协调者, 即找到服务端中管理这个消费者的协调者节点 ...

  2. 解决svn检出后不显示图标的问题

    解决svn检出后不显示图标的问题: 此文经过个人验证,可以解决TortoiseSVN图标显示异常问题: 问题出现原因:Windows Explorer Shell 支持 Overlay Icon 最多 ...

  3. vue实现商品累计效果

    vue实现商品累计需要以下几点 1.添加商品 2.选中 3.删除功能 4.总计功能 <div id="main"> <div class="con&qu ...

  4. [Android] Android 让UI控件固定于底部的几种方法

    Android 让UI控件固定于底部的几种方法1.采用linearlayout布局:android:layout_height="0dp" <!-- 这里不能设置fill_p ...

  5. Vector集合

    Vector集合也是List接口的一个实现类,但是它是同步的,这就意味着是单线程的,速度比较慢,被ArrayList集合所取代了(PS:为什么我现在也还不知道,先记录了)

  6. int、bool和str

    int bit_length 返回以二进制表示的最短长度 print(int.bit_length(10)) 结果 4 Process finished with exit code 0 int() ...

  7. html取消回车刷新提交

    <form class="weui-search-bar__form" onsubmit="return false;"> <form cla ...

  8. 从零开始搭建轻量级个人XSS平台

    一. 前言 决定搭建XSS平台是因为自己想深入学习一下XSS相关的知识,多多进行实践,上网搜索了一下XSS平台有很多,但是总觉得不是很安全,这个毕竟敏感信息要传输到陌生人的服务器上,而且服务器端测试代 ...

  9. Immunity Debugger学习 二

    1.Exploit开发 发现漏洞只是一个开始,在你完成利用程序之前,还有很长一段路要走.不过Immunity专门为了这项任务做了许多专门设计,相信能帮你减少不少痛苦.接下来我们开发一些PyComman ...

  10. spring data jpa 关键字 命名

    http://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#repository-query-keywords