平衡树(Splay):Splaytree POJ 3580 SuperMemo
Description
Your friend, Jackson is invited to a TV show called SuperMemo in which the participant is told to play a memorizing game. At first, the host tells the participant a sequence of numbers, {A1, A2, ... An}. Then the host performs a series of operations and queries on the sequence which consists:
- ADD x y D: Add D to each number in sub-sequence {Ax ... Ay}. For example, performing "ADD 2 4 1" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5, 5}
- REVERSE x y: reverse the sub-sequence {Ax ... Ay}. For example, performing "REVERSE 2 4" on {1, 2, 3, 4, 5} results in {1, 4, 3, 2, 5}
- REVOLVE x y T: rotate sub-sequence {Ax ... Ay} T times. For example, performing "REVOLVE 2 4 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 2, 5}
- INSERT x P: insert P after Ax. For example, performing "INSERT 2 4" on {1, 2, 3, 4, 5} results in {1, 2, 4, 3, 4, 5}
- DELETE x: delete Ax. For example, performing "DELETE 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5}
- MIN x y: query the participant what is the minimum number in sub-sequence {Ax ... Ay}. For example, the correct answer to "MIN 2 4" on {1, 2, 3, 4, 5} is 2
To make the show more interesting, the participant is granted a chance to turn to someone else that means when Jackson feels difficult in answering a query he may call you for help. You task is to watch the TV show and write a program giving the correct answer to each query in order to assist Jackson whenever he calls.
Input
The first line contains n (n ≤ 100000).
The following n lines describe the sequence.
Then follows M (M ≤ 100000), the numbers of operations and queries.
The following M lines describe the operations and queries.
Output
For each "MIN" query, output the correct answer.
Sample Input
5
1
2
3
4
5
2
ADD 2 4 1
MIN 4 5
Sample Output
5
这也许是我目前见过最全面的平衡树的题目了,相信把这题搞透之后,平衡树也就差不多了,呃。
tips:这题我交了好多次才AC ~~~
思路其实很简单,主要是程序实现和各种细节给跪了。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn=;
const int INF=;
int Min[maxn],key[maxn],fa[maxn],ch[maxn][];
int flip[maxn],add[maxn],sz[maxn],rt,cnt,n,Q; void Push_up(int p){
Min[p]=min(key[p],min(Min[ch[p][]],Min[ch[p][]]));
sz[p]=sz[ch[p][]]+sz[ch[p][]]+;
} void Add(int p,int d){
if(p){
Min[p]+=d;
key[p]+=d;
add[p]+=d;
}
} void Flip(int p){
swap(ch[p][],ch[p][]);
flip[p]^=;
} void Push_down(int p){
if(add[p]){
Add(ch[p][],add[p]);
Add(ch[p][],add[p]);
add[p]=;
}
if(flip[p]){
Flip(ch[p][]);
Flip(ch[p][]);
flip[p]=;
}
} void Rotate(int x){
int y=fa[x],g=fa[y],c=ch[y][]==x;
ch[y][c]=ch[x][c^];
fa[ch[x][c^]]=y;fa[y]=x;
ch[x][c^]=y;fa[x]=g;
if(g)
ch[g][ch[g][]==y]=x;
Push_up(y);
} void Splay(int x,int g=){
for(int y;(y=fa[x])!=g;Rotate(x))
if(fa[y]!=g)
Rotate((ch[fa[y]][]==y)==(ch[y][]==x)?y:x);
Push_up(x);
if(!g)
rt=x;
} void Make_root(int x,int g=){
int p=rt;
while(true){
Push_down(p);
if(sz[ch[p][]]+==x)break;
if(sz[ch[p][]]+<x){
x-=sz[ch[p][]]+;
p=ch[p][];
}
else
p=ch[p][];
}
Splay(p,g);
} int Build(int pre,int l,int r){
if(l>r)return ;
int mid=(l+r)>>;
ch[mid][]=Build(mid,l,mid-);
if(mid>&&mid<n)
scanf("%d",&key[mid]);
else
key[mid]=INF;
Min[mid]=key[mid];
fa[mid]=pre;sz[mid]=;
ch[mid][]=Build(mid,mid+,r);
Push_up(mid);
return mid;
} int main(){
Min[]=;
scanf("%d",&n);n+=;
rt=Build(,,n);cnt=n;
scanf("%d",&Q);
char s[];int a,b,x;
while(Q--){
scanf("%s",s);
if(!strcmp(s,"ADD")){
scanf("%d%d%d",&a,&b,&x);a++;b++;
Make_root(a-);
Make_root(b+,rt);
Push_down(rt);
Push_down(ch[rt][]);
Add(ch[ch[rt][]][],x);
}
else if(!strcmp(s,"MIN")){
scanf("%d%d",&a,&b);a++;b++;
Make_root(a-);
Make_root(b+,rt);
Push_down(rt);
Push_down(ch[rt][]);
printf("%d\n",Min[ch[ch[rt][]][]]);
}
else if(!strcmp(s,"DELETE")){
scanf("%d",&x);x++;
Make_root(x-);
Make_root(x+,rt);
ch[ch[rt][]][]=;
Push_up(ch[rt][]);
Push_up(rt);
}
else if(!strcmp(s,"REVERSE")){
scanf("%d%d",&a,&b);a++;b++;
Make_root(a-);
Make_root(b+,rt);
Flip(ch[ch[rt][]][]);
}
else if(!strcmp(s,"INSERT")){
scanf("%d%d",&a,&x);a++;
Make_root(a);
Make_root(a+,rt);
int p=++cnt;sz[p]=;
ch[ch[rt][]][]=p;
key[p]=Min[p]=x;
fa[p]=ch[rt][];
Push_up(ch[rt][]);
Push_up(rt);
}
else if(!strcmp(s,"REVOLVE"))
{
scanf("%d%d%d",&a,&b,&x);a++;b++;
Make_root(a-);
Make_root(b+,rt);
x%=b-a+;
if(x){
Make_root(b-x);
Make_root(b+,rt);
int tmp=ch[ch[rt][]][];
ch[ch[rt][]][]=;
Push_up(ch[rt][]);
Push_up(rt);
Make_root(a-);
Make_root(a,rt);
ch[ch[rt][]][]=tmp;
fa[tmp]=ch[rt][];
Push_up(ch[rt][]);
Push_up(rt);
}
}
}
return ;
}
时隔多月,我学会了treap,再AC了一遍。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;
const int maxn=;
const int INF=;
int key[maxn],flip[maxn],add[maxn],cnt,rt;
int Min[maxn],sz[maxn],ch[maxn][],fix[maxn];
int x,y,z,t1,t2;
struct Treap{
void Init(){
Min[]=INF;
//srand(time(NULL)); poj上不能在G++上用这个,否则RE
} int Newnode(int v){
sz[++cnt]=;
Min[cnt]=key[cnt]=v;
flip[cnt]=add[cnt]=;
ch[cnt][]=ch[cnt][]=;
fix[cnt]=rand();
return cnt;
} void Push_up(int x){
sz[x]=sz[ch[x][]]+sz[ch[x][]]+;
Min[x]=min(min(Min[ch[x][]],Min[ch[x][]]),key[x]);
} void Flip(int x){
swap(ch[x][],ch[x][]);
flip[x]^=;
} void Add(int x,int d){
if(!x)return;
key[x]+=d;
Min[x]+=d;
add[x]+=d;
} void Push_down(int x){
if(add[x]){
Add(ch[x][],add[x]);
Add(ch[x][],add[x]);
add[x]=;
}
if(flip[x]){
Flip(ch[x][]);
Flip(ch[x][]);
flip[x]=;
}
} int Merge(int x,int y){
if(!x||!y)return x|y;
Push_down(x);
Push_down(y);
if(fix[x]<=fix[y]){
ch[x][]=Merge(ch[x][],y);
Push_up(x);
return x;
}
else{
ch[y][]=Merge(x,ch[y][]);
Push_up(y);
return y;
}
} void Split(int x,int k){
Push_down(x);
if(k>sz[x]){t1=x;t2=;return;} if(sz[ch[x][]]+==k){
t1=ch[x][];t2=x;
ch[x][]=;
Push_up(x);
return;
} if(sz[ch[x][]]+<k){
k-=sz[ch[x][]]+;
Split(ch[x][],k);
ch[x][]=t1;t1=x;
Push_up(x);
} else{
Split(ch[x][],k);
ch[x][]=t2;t2=x;
Push_up(x);
}
} void Insert(int k,int v){
Split(rt,k+);
t1=Merge(t1,Newnode(v));
rt=Merge(t1,t2);
} void Delete(int k){
int tmp;
Split(rt,k);tmp=t1;
Split(t2,);t1=tmp;
rt=Merge(t1,t2);
} void Divide(int l,int r){
Split(rt,l);x=t1;
Split(t2,r-l+);y=t1;z=t2;
} void Converge(){
x=Merge(x,y);
rt=Merge(x,z);
} void Add(int l,int r,int d){
Divide(l,r);Add(y,d);
Converge();
} void Reverse(int l,int r){
Divide(l,r);Flip(y);
Converge();
} void Revolve(int l,int r,int k){
Divide(l,r);
k%=sz[y];
if(k){
Split(y,sz[y]-k+);
y=Merge(t2,t1);
}
Converge();
} int Query(int l,int r){
Divide(l,r);
int ret=Min[y];
Converge();
return ret;
}
}T; int n,Q;
char op[]; int main(){
T.Init();
scanf("%d",&n);
for(int i=,a;i<=n;i++){
scanf("%d",&a);
T.Insert(i,a);
}
int l,r,k;
scanf("%d",&Q);
while(Q--){
scanf("%s",op);
if(!strcmp(op,"ADD")){
scanf("%d%d%d",&l,&r,&k);
T.Add(l,r,k);
}
else if(!strcmp(op,"REVERSE")){
scanf("%d%d",&l,&r);
T.Reverse(l,r);
}
else if(!strcmp(op,"REVOLVE")){
scanf("%d%d%d",&l,&r,&k);
T.Revolve(l,r,k);
}
else if(!strcmp(op,"INSERT")){
scanf("%d%d",&l,&k);
T.Insert(l,k);
}
else if(!strcmp(op,"DELETE")){
scanf("%d",&k);
T.Delete(k);
}
else if(!strcmp(op,"MIN")){
scanf("%d%d",&l,&r);
printf("%d\n",T.Query(l,r));
}
}
return ;
}
有些地方没打好,很丑……
决定日后整理为模板。
平衡树(Splay):Splaytree POJ 3580 SuperMemo的更多相关文章
- poj 3580 SuperMemo
题目连接 http://poj.org/problem?id=3580 SuperMemo Description Your friend, Jackson is invited to a TV sh ...
- POJ 3580 - SuperMemo - [伸展树splay]
题目链接:http://poj.org/problem?id=3580 Your friend, Jackson is invited to a TV show called SuperMemo in ...
- Splay树(多操作)——POJ 3580 SuperMemo
相应POJ题目:点击打开链接 SuperMemo Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 11309 Accept ...
- POJ 3580 SuperMemo (splay tree)
SuperMemo Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 6841 Accepted: 2268 Case Ti ...
- POJ 3580 SuperMemo (FHQ_Treap)
题意:让你维护一个序列,支持以下6种操作: ADD x y d: 第x个数到第y个数加d . REVERSE x y : 将区间[x,y]中的数翻转 . REVOLVE x y t :将区间[x,y] ...
- POJ 3580 SuperMemo 伸展树
题意: 维护一个序列,支持如下几种操作: ADD x y D:将区间\([x,y]\)的数加上\(D\) REVERSE x y:翻转区间\([x,y]\) REVOLVE x y T:将区间\([x ...
- Hihocoder 1329 平衡树·Splay(平衡树)
Hihocoder 1329 平衡树·Splay(平衡树) Description 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. 小Hi:怎么了? 小Ho:小H ...
- hiho #1329 : 平衡树·Splay
#1329 : 平衡树·Splay 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. ...
- 【BZOJ3224】Tyvj 1728 普通平衡树 Splay
Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数 ...
随机推荐
- PRD产品需求文档概要
PRD概念 PRM就是Product Requirements Document的简称,也就是产品需求模型.一般来说一个产品会伴随有市场需求文档(Market Requirements Documen ...
- mysql复习笔记
阅读目录 1.什么是SQL语句2.使用sql语句创建数据库和表3.创建数据表4.数据完整性约束5.四中基本字符类型说明6.SQL基本语句7.类型转换函数8.日期函数9.数学函数10.字符串函数11.联 ...
- 2016年11月1日——jQuery源码学习笔记
1.instanceof运算符希望左操作数是一个对象,右操作数标识对象的类.如果左侧的对象是右侧类的实例,则表达式返回true,否则返回false 2.RegExp.exec() 如果 exec() ...
- Java-Hibernate官方英文文档地址
Hibernate官方英文文档地址 http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/
- oracle中不曾熟悉的 to_char、to_number(未完待续)
十进制 十六进制88 58 用法一:Converts a HEX number to o FLOAT (转换一个十六进制数的浮标) SQL> sele ...
- I/O多路转接之select
系统提供select函数来实现多路复⽤用输入/输出模型.select系统调用是用来让我们的程序监视 多个文件句柄的状态变化的.程序会停在select这里等待,直到被监视的文件句柄有一个或 多个发生了状 ...
- STL库list::sort()实现深度解析
原创,转载请注明出处:STL库list::sort()实现深度解析 list模板的定义以及一些基本成员函数的实现这里我就不赘述了,还不清楚的同学可以到网上查找相关资料或者直接查看侯捷翻译的<ST ...
- jQuery慢慢啃之文档处理(五)
1.append(content|fn)//向每个匹配的元素内部追加内容. $("p").append("<b>Hello</b>"); ...
- .net软件工程师面试题(参考答案)
一.填空题(每空1分,共12分) 1面向对象的语言具有__封装______性.__继承_______性.__多态______性. 2能用foreach遍历访问的对象需要实现 ____Ienumerab ...
- 03:计算(a+b)/c的值
总时间限制: 1000ms 内存限制: 65536kB 描述 给定3个整数a.b.c,计算表达式(a+b)/c的值,/是整除运算. 输入 输入仅一行,包括三个整数a.b.c, 数与数之间以一个空格 ...