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. URAL 2032 - Conspiracy Theory and Rebranding【本源勾股数组】

    [题意] 给出三角形的三个边长,均是10^7以内的整数,问三角形的三个角的坐标是否能均是整数,输出其中任意一个解. [题解] 一开始想的是枚举一条边的横坐标,然后通过勾股定理以及算角度求出其他点的坐标 ...

  2. opencart 模块开发详解

    opencart 模块开发详解 由 xiekanxiyang » 2013年 7月 11日 10:17 pm opencart 将页面分成若干模块, 每个模块可以有多个实例(可能这样说不是很恰当) 每 ...

  3. post和get的区别?

    1. get是从服务器上获取数据,post是向服务器传送数据.2. get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到.post是通过H ...

  4. App上线基本流程

    还可参考的:http://www.cocoachina.com/bbs/read.php?tid=330302 iOS项目上传前期准备材料: 1.已有开发者账号 2.已有发布证书 3.一张1024*1 ...

  5. 极端气候频现 五款开发天气预报应用的API

    http://www.csdn.net/article/2014-02-07/2818322-weather-forecast-api-for-developing-apps

  6. 读懂IL代码(二)

    上一篇提到了最基本的IL代码,应该是比较通俗易懂的,所以有了上一篇的基础之后,这篇便要深入一点点的来讲述了. 首先我必须再来说一些重要的概念: Evaluation Stack(评估栈):这是由.NE ...

  7. Asp.net 实现图片缩放 无水印(方法一)

    /// <summary> /// 图片缩放 无水印 /// </summary> /// <param name="sourceFile">图 ...

  8. js 中的流程控制-条件语句

    条件语句: if(exp)执行一句代码 <script> var x = 1 ; if(x == 1 ) //当if判断语句结果是true 或者 false 当判断结果等于true的时候, ...

  9. WdatePicker.js 日期时间插件

    支持功能: 1.支持常规在input单击或获得焦点时调用,还支持使用其他的元素如:<img><div>等触发WdatePicker函数来调用弹出日期框 @1.input 调用: ...

  10. python【第六篇】面向对象编程

    面向对象编程 一.编程范式:编程的方法论.程序员编程的“套路”及“特点”特点总结,抽象成方法.规范. 二.面向对象编程介绍: 1.描述 世界万物,皆可分类:世间万物,皆为对象:只要是对象,就肯定属于某 ...