POJ3580:SuperMemo
浅谈\(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的更多相关文章
- POJ 3580:SuperMemo(Splay)
http://poj.org/problem?id=3580 题意:有6种操作,其中有两种之前没做过,就是Revolve操作和Min操作.Revolve一开始想着一个一个删一个一个插,觉得太暴力了,后 ...
- 【无旋式treap】例题
[bzoj3223]文艺平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[ ...
- 【无旋 treap】例题
[bzoj3223]文艺平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[ ...
- java web 开发三剑客 -------电子书
Internet,人们通常称为因特网,是当今世界上覆盖面最大和应用最广泛的网络.根据英语构词法,Internet是Inter + net,Inter-作为前缀在英语中表示“在一起,交互”,由此可知In ...
- 所有selenium相关的库
通过爬虫 获取 官方文档库 如果想获取 相应的库 修改对应配置即可 代码如下 from urllib.parse import urljoin import requests from lxml im ...
- 平衡树(Splay):Splaytree POJ 3580 SuperMemo
SuperMemo Description Your friend, Jackson is invited to a TV show called SuperMemo in which ...
- poj3580 SuperMemo (Splay+区间内向一个方向移动)
Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 13550 Accepted: 4248 Case Time Limit: ...
- 【POJ3580】【splay版】SuperMemo
Description Your friend, Jackson is invited to a TV show called SuperMemo in which the participant i ...
- 【POJ3580】【块状链表】SuperMemo
Description Your friend, Jackson is invited to a TV show called SuperMemo in which the participant i ...
随机推荐
- oracle恢复已经删除的数据
insert into tablerestore select * from tablerestore as of timestamp to_Date('2014-8-8 15:00:00','yyy ...
- 基于togglepoolmember.pl编写F5设备控制模块
为了方便利用python对F5设备进行操作,本文将togglepoolmember.pl对F5设备的控制写成了python模块,源代码例如以下: #!/usr/bin/python # -*- cod ...
- 通配符的匹配很全面, 但无法找到元素 'context:component-scan' 的声明。
错误原因: xml文件中,本来是要配置成下面这样的: http://www.springframework.org/schema/context http://www.springframework. ...
- Jquery 常用方法总结
1.Attribute(属性): $(”p”).addClass(css中定义的样式类型); 给某个元素添加样式 $(”img”).attr({src:”test.jpg”,alt:”test Ima ...
- 【demo练习四】:WPF用户控件案例
首先,新建vs中“用户控件(WPF)”,右键项目名 =>"添加"按钮 => 选择“新建项”. 然后选择“用户控件(WPF)” => 起名字 => 点击“添加 ...
- 18- php Redis扩展编译
一:php扩展编译Redis :wget http://pecl.php.net/get/redis-2.2.5.tgz :tar -zxvf redis-.tgz :cd redis- :/usr/ ...
- Cocos2d-x 3.0final 终结者系列教程16-《微信飞机大战》实现
看到cocos2d-x推出了3.1版本号,真是每月一次新版本号,速度. 另一个好消息就是http://cn.cocos2d-x.org/上线了,祝贺!啥时候把我的视频和教程放上去呢?!! . 视频下载 ...
- 九度OJ 1032:ZOJ (基础题)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:4569 解决:2561 题目描述: 读入一个字符串,字符串中包含ZOJ三个字符,个数不一定相等,按ZOJ的顺序输出,当某个字符用完时,剩下的 ...
- terminal中 启动ios模拟器,并安装软件
启动运行模拟器: xcrun instruments -w 'iPhone 6 Plus' 在已经启动好的模拟器中安装应用: xcrun simctl install booted Calculato ...
- Other Linker flags 添加 -Objc导致包冲突
Other Linker flags 添加 -Objc导致包冲突 先尝试不添加-Objc,不行的话尝试下面的方法. 第三方冲突解决办法: https://www.jianshu.com/p/02846 ...