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 ...
随机推荐
- linux下网卡绑定
网卡绑定的作用:1.冗余,防止单点故障 2.防止传输瓶颈 1.交换机端口绑定: system-view link-aggregation group 1 mode manual 比如把端口1和2进行绑 ...
- python 基础 1.5 python 数据类型(一)--整型 浮点型 布尔型及字符串和常用方法
一.python 数据类型:数值,字符串,列表,元组,字典.以下操作是在linux 下 ipython中进行 1.数值 1>123 与 “123”的区别 答:123为数值,“123”在pyt ...
- 开发环境部署git 步骤
1.安装完后,打开git bash. vim .gitconfig 此文件放在用户目录,即 git bash 打开后默认位置. 2.插入以下内容,保存 [user] name = email = [ ...
- 【题解】 P5022旅行
[题解]P5022 旅行 当给定你一颗树的时候,这题就是一道送分题,凉心啊! 但是给定你一颗基环树呢? 暴力断环直接跑. 但是数据范围\(n\le 1000\) 乱做就完事了. 考场上这样想的,对于\ ...
- 7-6 公路村村通(30 分) 【prime】
7-6 公路村村通(30 分) 现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本. 输入格式: 输入数据包括城镇数目正整数N(≤10 ...
- IOS平台的几个推送服务的对比
http://blog.163.com/scuqifuguang@126/blog/static/171370086201399113833299/ 最近研究了一下极光推送(JPush) ...
- 【转】Java中的代码点与代码单元
转载自:http://blog.csdn.net/xujinsmile/article/details/8526387 最近看core java,之前一直不明白,看了不少帖子和博客,总算搞明白了. J ...
- Android Weekly Notes Issue #322
Android Weekly Issue #322 August 12th, 2018 Android Weekly Issue #322. 本期内容包括: 键盘的图像支持; 网络安全实现; Kotl ...
- 跟我一起学Git (十) Patches【转】
本文转载自:http://cs-cjl.com/2014/05/05/learn_git_with_me_10 Git实现了以下三条用于交换patch的命令: git format-patch 用于创 ...
- Django 之 Paginator 分页功能
Django Paginator Django 分页官方文档 https://docs.djangoproject.com/en/1.10/topics/pagination/ 此分页方法没有限制显 ...