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 ...
随机推荐
- openwrt patch
一: 这几天使用一款电信的4G网卡,发现了一些问题,所以决定打个pitch来解决问题,顺便把patch的生成与使用学习一下 二:安装patch的管理工具quilt 1. sudo apt-get in ...
- 资源重复 uac.res resource kept(转)
一般按照网上流传的方法制作UAC.RES放到DELPHI程序里面来就可以出现盾牌.但是某些DELPHI的项目在添加了UAC.RES后编译会报错,例如: [DCC Error] E2161 Warnin ...
- AWR元数据的迁移或导入到其它数据库
我们能够将AWR元数据迁移(导入)到其它数据库.低版本号的导入到高版本号,再用高版本号的数据库生成AWR报告,也能使用一些新特性,如 SQL ordered by Physical Reads (Un ...
- 你的JVM还好吗?GC初步诊断
你的JVM还好吗?GC初步诊断 阿飞的博客 JVM的GC机制绝对是很多程序员的福音,它让Java程序员省去了自己回收垃圾的烦恼.从而可以把大部分时间专注业务身上,大大提高了业务开发速度,让产品 ...
- 22 nginx配置与集群
一:编译nginx ,并配置 Cd /app/pcre-8.12 ./configure Make && make install Cd nginx-1.2.7 ./configure ...
- ASP.NET MVC 相关的社群与讨论区
ASP.NET MVC 官方论坛 http://forums.asp.net/1146.aspx 台湾微软MSDN论坛 --- ASP.NET 与 AJAX(ASP.NET AND AJAX)讨论区 ...
- jquery实现重置
$('#reset').click(function(){ $('#info_frm')[0].reset(); });
- 跳过权限检查,强制修改mysql密码
windows: 1,停止MYSQL服务,CMD打开DOS窗口,输入 net stop mysql 2,在CMD命令行窗口,进入MYSQL安装目录 比如E:\Program Files\MySQL\M ...
- 矩阵十题【六】 poj3070 Fibonacci
题目链接:http://poj.org/problem? id=3070 题目大意:给定n和10000,求第n个Fibonacci数mod 10000 的值,n不超过2^31. 结果保留四位数字. 非 ...
- Method invoke 方法
这个问题要看明白源码才能解决