浅谈\(splay\):https://www.cnblogs.com/AKMer/p/9979592.html

浅谈\(fhq\)_\(treap\):https://www.cnblogs.com/AKMer/p/9981274.html

题目传送门:http://poj.org/problem?id=3580

对于\(REVOLVE\)操作,就相当于把\([r-t+1,r]\)剪切下来粘贴到\([l-1,l]\)中间,其余的操作都是平衡树较为模板的操作了。记得把零号点的最小值赋成\(inf\),要不然空儿子更新父亲信息就会出错。下传标记记得不要传给空儿子,否则会加爆。

时间复杂度:\(O((n+m)logn)\)

空间复杂度:\(O(n)\)

\(splay\)代码如下:

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std; const int maxn=2e5+5,inf=2e9; int n,m;
char s[10];
int a[maxn]; int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
} struct Splay {
int tot,root;
bool rev[maxn];
int add[maxn],val[maxn],mn[maxn];
int siz[maxn],fa[maxn],son[maxn][2]; int newnode(int v) {
siz[++tot]=1;
val[tot]=mn[tot]=v;
return tot;
} void update(int p) {
siz[p]=siz[son[p][0]]+1+siz[son[p][1]];
mn[p]=min(min(mn[son[p][0]],mn[son[p][1]]),val[p]);
} void build(int l,int r,int lst) {
if(r<l)return;
if(l==r) {
siz[l]=1,val[l]=mn[l]=a[l];
fa[l]=lst,son[lst][l>lst]=l;
return;
}
int mid=(l+r)>>1;
val[mid]=a[mid];
fa[mid]=lst,son[lst][mid>lst]=mid;
build(l,mid-1,mid),build(mid+1,r,mid);
update(mid);
} void prepare() {
mn[0]=inf,tot=n+2,build(1,n+2,0),root=(n+3)>>1;
} void make_rev_tag(int p) {
if(!p)return;
rev[p]^=1,swap(son[p][0],son[p][1]);
} void make_add_tag(int p,int v) {
if(!p)return;
val[p]+=v,add[p]+=v,mn[p]+=v;
} void push_down(int p) {
if(rev[p]) {
make_rev_tag(son[p][0]);
make_rev_tag(son[p][1]);
rev[p]=0;
}
if(add[p]) {
make_add_tag(son[p][0],add[p]);
make_add_tag(son[p][1],add[p]);
add[p]=0;
}
} int find(int u,int rk) {
push_down(u);
if(siz[son[u][0]]+1==rk)return u;
if(siz[son[u][0]]>=rk)return find(son[u][0],rk);
return find(son[u][1],rk-siz[son[u][0]]-1);
} int t(int u) {
return son[fa[u]][1]==u;
} void rotate(int u) {
int ret=t(u),f=fa[u],s=son[u][ret^1];
son[f][ret]=s;if(s)fa[s]=f;son[u][ret^1]=f;
fa[u]=fa[f];if(fa[f])son[fa[f]][t(f)]=u;
fa[f]=u;update(f),update(u);
} void splay(int goal,int u) {
int tmp=fa[goal];
while(fa[u]!=tmp) {
if(fa[fa[u]]!=tmp) {
if(t(fa[u])==t(u))rotate(fa[u]);
else rotate(u);
}
rotate(u);
}
if(!tmp)root=u;
} void ADD(int l,int r,int v) {
int u1=find(root,l-1),u2=find(root,r+1);
splay(root,u1),splay(son[u1][1],u2);
make_add_tag(son[u2][0],v);
update(u2),update(u1);
} void REVERSE(int l,int r) {
int u1=find(root,l-1),u2=find(root,r+1);
splay(root,u1),splay(son[u1][1],u2);
make_rev_tag(son[u2][0]);
} int cut(int l,int r) {
int u1=find(root,l-1),u2=find(root,r+1);
splay(root,u1),splay(son[u1][1],u2);
int tmp=son[u2][0];
son[u2][0]=fa[tmp]=0;
update(u2),update(u1);
return tmp;
} void paste(int pos,int node) {
int u1=find(root,pos-1),u2=find(root,pos);
splay(root,u1),splay(son[u1][1],u2);
fa[node]=u2,son[u2][0]=node;
update(u2),update(u1);
} int query(int l,int r) {
int u1=find(root,l-1),u2=find(root,r+1);
splay(root,u1),splay(son[u1][1],u2);
return mn[son[u2][0]];
}
}T; int main() {
n=read();
for(int i=2;i<=n+1;i++)
a[i]=read();
a[1]=a[n+2]=inf;
T.prepare();m=read();
for(int i=1;i<=m;i++) {
scanf("%s",s+1);
if(s[1]=='A') {
int l=read()+1,r=read()+1,v=read();
T.ADD(l,r,v);
}
if(s[1]=='R') {
int l=read()+1,r=read()+1;
if(s[4]=='E')T.REVERSE(l,r);
else {
int t=read()%(r-l+1);
int tmp=T.cut(r-t+1,r);
T.paste(l,tmp);
}
}
if(s[1]=='I') {
int pos=read()+1,v=read();
T.paste(pos+1,T.newnode(v));
}
if(s[1]=='D') {
int pos=read()+1;
T.cut(pos,pos);
}
if(s[1]=='M') {
int l=read()+1,r=read()+1;
printf("%d\n",T.query(l,r));
}
}
return 0;
}

\(fhq\)_\(treap\)版代码如下:

#include <ctime>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii; const int maxn=2e5+5,inf=2e9; int n,m;
char s[10];
int a[maxn]; int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
} struct fhq_treap {
int tot,root;
bool rev[maxn];
int val[maxn],mn[maxn],add[maxn];
int siz[maxn],fix[maxn],son[maxn][2]; int newnode(int v) {
siz[++tot]=1;
fix[tot]=rand();
val[tot]=mn[tot]=v;
return tot;
} void update(int p) {
siz[p]=siz[son[p][0]]+1+siz[son[p][1]];
mn[p]=min(min(mn[son[p][0]],mn[son[p][1]]),val[p]);
} void build(int l,int r,int lst) {
if(r<l)return;
if(l==r) {
siz[l]=1,fix[l]=rand();
son[lst][l>lst]=l;
val[l]=mn[l]=a[l];
return;
}
int mid=(l+r)>>1;
val[mid]=a[mid],fix[mid]=rand();
son[lst][mid>lst]=mid;
build(l,mid-1,mid),build(mid+1,r,mid);
update(mid);
} void prepare() {
mn[0]=inf,tot=n,build(1,n,0),root=(n+1)>>1;
} void make_add_tag(int u,int v) {
if(!u)return;
val[u]+=v,add[u]+=v,mn[u]+=v;
} void make_rev_tag(int u) {
if(!u)return;
rev[u]^=1,swap(son[u][0],son[u][1]);
} void push_down(int u) {
if(add[u]) {
make_add_tag(son[u][0],add[u]);
make_add_tag(son[u][1],add[u]);
add[u]=0;
}
if(rev[u]) {
make_rev_tag(son[u][0]);
make_rev_tag(son[u][1]);
rev[u]=0;
}
} pii split(int u,int rk) {
if(!rk)return make_pair(0,u);
if(rk==siz[u])return make_pair(u,0);
push_down(u);
if(siz[son[u][0]]>=rk) {
pii tmp=split(son[u][0],rk);
son[u][0]=tmp.second,update(u);
return make_pair(tmp.first,u);
}
else {
pii tmp=split(son[u][1],rk-siz[son[u][0]]-1);
son[u][1]=tmp.first,update(u);
return make_pair(u,tmp.second);
}
} int merge(int a,int b) {
if(!a||!b)return a+b;
push_down(a),push_down(b);
if(fix[a]>fix[b])return son[a][1]=merge(son[a][1],b),update(a),a;
else return son[b][0]=merge(a,son[b][0]),update(b),b;
} void ADD(int l,int r,int v) {
pii tmp1=split(root,r);
pii tmp2=split(tmp1.first,l-1);
make_add_tag(tmp2.second,v);
root=merge(merge(tmp2.first,tmp2.second),tmp1.second);
} void REVERSE(int l,int r) {
pii tmp1=split(root,r);
pii tmp2=split(tmp1.first,l-1);
make_rev_tag(tmp2.second);
root=merge(merge(tmp2.first,tmp2.second),tmp1.second);
} int cut(int l,int r) {
pii tmp1=split(root,r);
pii tmp2=split(tmp1.first,l-1);
root=merge(tmp2.first,tmp1.second);
return tmp2.second;
} void paste(int pos,int node) {
pii tmp=split(root,pos-1);
root=merge(merge(tmp.first,node),tmp.second);
} int query(int l,int r) {
pii tmp1=split(root,r);
pii tmp2=split(tmp1.first,l-1);
int res=mn[tmp2.second];
root=merge(merge(tmp2.first,tmp2.second),tmp1.second);
return res;
}
}T; int main() {
srand(time(0)),n=read();
for(int i=1;i<=n;i++)
a[i]=read();
T.prepare();m=read();
for(int i=1;i<=m;i++) {
scanf("%s",s+1);
if(s[1]=='A') {
int l=read(),r=read(),v=read();
T.ADD(l,r,v);
}
if(s[1]=='R') {
int l=read(),r=read();
if(s[4]=='E')T.REVERSE(l,r);
else {
int t=read()%(r-l+1);
int tmp=T.cut(r-t+1,r);
T.paste(l,tmp);
}
}
if(s[1]=='I') {
int pos=read(),v=read();
T.paste(pos+1,T.newnode(v));
}
if(s[1]=='D') {
int pos=read();
T.cut(pos,pos);
}
if(s[1]=='M') {
int l=read(),r=read();
printf("%d\n",T.query(l,r));
}
}
return 0;
}

POJ3580:SuperMemo的更多相关文章

  1. POJ 3580:SuperMemo(Splay)

    http://poj.org/problem?id=3580 题意:有6种操作,其中有两种之前没做过,就是Revolve操作和Min操作.Revolve一开始想着一个一个删一个一个插,觉得太暴力了,后 ...

  2. 【无旋式treap】例题

    [bzoj3223]文艺平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[ ...

  3. 【无旋 treap】例题

    [bzoj3223]文艺平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[ ...

  4. java web 开发三剑客 -------电子书

    Internet,人们通常称为因特网,是当今世界上覆盖面最大和应用最广泛的网络.根据英语构词法,Internet是Inter + net,Inter-作为前缀在英语中表示“在一起,交互”,由此可知In ...

  5. 所有selenium相关的库

    通过爬虫 获取 官方文档库 如果想获取 相应的库 修改对应配置即可 代码如下 from urllib.parse import urljoin import requests from lxml im ...

  6. 平衡树(Splay):Splaytree POJ 3580 SuperMemo

    SuperMemo         Description Your friend, Jackson is invited to a TV show called SuperMemo in which ...

  7. poj3580 SuperMemo (Splay+区间内向一个方向移动)

    Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 13550   Accepted: 4248 Case Time Limit: ...

  8. 【POJ3580】【splay版】SuperMemo

    Description Your friend, Jackson is invited to a TV show called SuperMemo in which the participant i ...

  9. 【POJ3580】【块状链表】SuperMemo

    Description Your friend, Jackson is invited to a TV show called SuperMemo in which the participant i ...

随机推荐

  1. JS 的引用赋值与传值赋值

    这个问题说大不大说小不小,如果你有幸踩了这个坑,一定会找这篇文章,哈哈~ 现说一下JS数字的类型:基本类型和引用类型 先看下下面两个栗子: var a = 30; var b = a; a = 20; ...

  2. spring boot json 首字母大小写问题解决方案

     spring boot默认使用的json解析框架是jackson,对于.net转java的项目来说太坑了,首字母大写的属性会自动转为小写,然后前端就悲剧了,十几个属性的ViewModel增加几个Js ...

  3. 相机标准之onvif---开放型网络视频接口论坛onvif 简介

    什么是ONVIF ? ONVIF:原意为 开放型网络视频接口论坛,即 Open Network Video Interface Forum ,是安讯士.博世.索尼等三家公司在2008年共同成立的一个国 ...

  4. Oracle学习第一篇—安装和简单语句

    一 安装  10G ----不适合Win7 Visual Machine-++++Visual Hard Disk 先安装介质(VM)---便于删除 11G-----适合Win7 1 把win64_1 ...

  5. 【Android】带底部指示的自定义ViewPager控件

    在项目中经常需要使用轮转广告的效果,在android-v4版本中提供的ViewPager是一个很好的工具,而一般我们使用Viewpager的时候,都会选择在底部有一排指示物指示当前显示的是哪一个pag ...

  6. MongoDB 基本操作具体解释

    MongoDB 最大的特点是他支持的查询语言很强大,其语法有点类似于面向对象的查询语 言.差点儿能够实现类似关系数据库单表查询的绝大部分功能,并且还支持对数据建立索引. 最后因为 MongoDB 能够 ...

  7. 使用ZipArchive解压

    本文转载至 http://www.apkbus.com/forum.php?mod=viewthread&tid=131390&extra=page%3D1 qqpk360 该用户从未 ...

  8. 在ios中使用单例模式编程

    本文转载至 http://blog.csdn.net/remote_roamer/article/details/7107007     1.    @implementation Singleton ...

  9. 计算机网络 --万维网www

    万维网是一个分布式的超媒体系统,客户程序向服务器程序发出请求,服务器程序向客户程序送回客户所需要的万维网文档.万维网必须解决的几个问题:1.怎样标志分布在整个因特网上的万维网文档?答:万维网使用统一的 ...

  10. vscode webstrom 配置 eslint 使用 airbnb 规范

    1.安装eslint npm eslint-plugin-react eslint-plugin-import babel-eslint -g 2.全局配置文件,放到c:/user/***/ { &q ...