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, {A1A2, ... An}. Then the host performs a series of operations and queries on the sequence which consists:

  1. 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}
  2. 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}
  3. REVOLVE x y T: rotate sub-sequence {Ax ... AyT times. For example, performing "REVOLVE 2 4 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 2, 5}
  4. 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}
  5. DELETE x: delete Ax. For example, performing "DELETE 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5}
  6. 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 (≤ 100000).

The following n lines describe the sequence.

Then follows 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的更多相关文章

  1. poj 3580 SuperMemo

    题目连接 http://poj.org/problem?id=3580 SuperMemo Description Your friend, Jackson is invited to a TV sh ...

  2. POJ 3580 - SuperMemo - [伸展树splay]

    题目链接:http://poj.org/problem?id=3580 Your friend, Jackson is invited to a TV show called SuperMemo in ...

  3. Splay树(多操作)——POJ 3580 SuperMemo

    相应POJ题目:点击打开链接 SuperMemo Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 11309   Accept ...

  4. POJ 3580 SuperMemo (splay tree)

    SuperMemo Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 6841   Accepted: 2268 Case Ti ...

  5. POJ 3580 SuperMemo (FHQ_Treap)

    题意:让你维护一个序列,支持以下6种操作: ADD x y d: 第x个数到第y个数加d . REVERSE x y : 将区间[x,y]中的数翻转 . REVOLVE x y t :将区间[x,y] ...

  6. POJ 3580 SuperMemo 伸展树

    题意: 维护一个序列,支持如下几种操作: ADD x y D:将区间\([x,y]\)的数加上\(D\) REVERSE x y:翻转区间\([x,y]\) REVOLVE x y T:将区间\([x ...

  7. Hihocoder 1329 平衡树·Splay(平衡树)

    Hihocoder 1329 平衡树·Splay(平衡树) Description 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. 小Hi:怎么了? 小Ho:小H ...

  8. hiho #1329 : 平衡树·Splay

    #1329 : 平衡树·Splay 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. ...

  9. 【BZOJ3224】Tyvj 1728 普通平衡树 Splay

    Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数 ...

随机推荐

  1. python下载IGS观测数据

    最近在学习GPS数据软件处理,经常需要下载数据练习,反复去网站上很麻烦,于是就写了一个小小的爬虫,用的是韩国的服务器,使用了python中的ftplib库实现的 今天稍微改了一下代码,可以选择卫星系统 ...

  2. Quartz.NET配置(Log4net)

    最近有个任务关于服务调度,想起以前看过Quartz.NET调度任务非常棒. 今天小试Quartz.NET,前面配置Quartz.NET很轻松,控制台也输出了.但是想配合Log4net来做日志文件,怎么 ...

  3. Log4j配置的经典总结,打印日志文件,日志存库

        一.介绍 Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制 日志信息输送的目的地是控制台.文件.GUI组件.甚至是套接口服务 器.NT的事件记录器.UNIX Sy ...

  4. asp.net 在线人数统计\页面访问量

    1.新建网站,添加几个窗体.webForm1.aspx ,ViewStateForm.aspx 2.在网站的根目录下添加全局应用程序类“Global.aspx” .(重要) 3.在“Global.as ...

  5. Linux 关于解压

    1.*.tar 用 tar –xvf 解压 2.*.gz 用 gzip -d或者gunzip 解压 3.*.tar.gz和*.tgz 用 tar –xzf 解压 4.*.bz2 用 bzip2 -d或 ...

  6. C++中extern关键字使用(转)

    参考文章:http://blog.csdn.net/sruru/article/details/7951019 chapter1.如何混合编译C语言和C++ 实际开发过程中,C++中会调用C与语言编写 ...

  7. 理解pkg-config工具

    你在 Unix 或 Linux 下开发过软件吗?写完一个程序,编译运行完全正常,在你本机上工作得好好的,你放到源代码管理系统中.然后,告诉你的同事说,你可以取下来用了.这时,你长长的出了一口气,几天的 ...

  8. cocos2d-x编译错误问题

    在xcode中创建的cocos2d-x项目,然后添加了一个基类,里面有虚方法,编译时出错,错误如下: Undefined symbols for architecture x86_64: " ...

  9. Ajax实现的长轮询不阻塞同一时间内页面的其他Ajax请求(同域请求)

    最近要做一个来电的弹屏功能,利用OM 系统的接口,OM系统发送请求到接口程序,分析数据添加到mysql数据库中,然后把最新的数据id 跟今日来电的总的数量存储到memcache 中.弹屏程序根据读取的 ...

  10. C语言-01基础语法

    1)         总结常见文件的拓展名 .c 是C语言源文件,在编写代码的时候创建 .o 是目标文件,在编译成功的时候产生 .out 是可执行文件,在链接成功的时候产生 2)         总结 ...