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. Sql Server 中事务(begin tran/commit tran/rollback tran)的用法

    ALTER PROCEDURE [dbo].[Proc_Test_commit1]     @result int output, --成功 1; 失败 0     @message nvarchar ...

  2. CakePHP之控制器

    控制器 控制器是MVC中的“C”. 如果你的网站使用Cake框架制作,一般根据url地址和通过路由,就会找到正确的控制器,然后控制器的动作就会被调用. 一个控制器需要解释请求数据.确保使用正确的模型. ...

  3. 解决dispaly:inline-block 遗留间隙的问题

    今天做一个项目 .本来我打算是作成表格的 ,后来觉得太费事直接搞成一个div 里面直接放四个a ,然后我将a 设置成inline-block.刚开始还没发现任何间隙问题,(对了说到这里 博主给新手介绍 ...

  4. 根据CreateDirectory递归创建多级目录

    分为MFC下的和非MFC下的两种,MFC路径是CString类型的,非MFC的路径是wstring类型的. 下面是MFC下的创建目录: void __fastcall RecursiveDirecto ...

  5. python使用VBA:Excel创建图表(转)

    # -*- coding: utf-8 -*- """ Created on Thu Mar 06 11:22:03 2014 @author: Administrato ...

  6. mysql更新密码为空

    1.进入命令行 mysql -u root -p 'oldpassword'; 2 修改root用户的密码:mysql> update mysql.user set password=PASSW ...

  7. 行列的几种命名方式.line-.colume======.row-.col=========.tr-.td

    第一种从line-height的语义来来讲,line表示hang再贴切不过了,colume纵列或者柱子也很形象,缺点太长了 第二种组合模拟rowspan,colspan而来,想必这个col也是colu ...

  8. slice的用法与用量

    用法:slice用于从指定值截取并返回新数组,但原数组结构不变 arrayObject.slice(start,[end]) 起始值可以为负数,-1为最后一个,end选填,但取不到end坐标的值,实际 ...

  9. EasyUI 1.3之前DataGrid中动态选中、获取Checkbox

    这几天做项目,由于项目中用到的EasyUI版本过低,不能使用自带操作DataGrid中CheckBox的方法. 所以自己写了一个临时方案: 根据ID集合选中所属行的CheckBox: data={1, ...

  10. 在vs code中使用ftp-sync插件实现客户端与服务器端代码的同步

    在vs code中使用ftp-sync插件实现客户端与服务器端代码的同步 下载安装 vscode-ftp-sync 插件. 安装方法1. Ctrl+Shift+P 输入 ext install [插件 ...