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. 16、SQL Server 复制及常见错误处理

    SQL Server 复制 复制是一组技术的组合,可以用此组合对数据和数据库对象进行复制由一个数据库移动到另一个数据库. 复制的英文是Replication,重复的意思,而不是Copy.复制的核心功能 ...

  2. 分离数据库(Detach database).

    Many times, we often needs to detach our databases if we want to copy it to another database instanc ...

  3. 动软代码生成器三层用于winform

    DBUtility项目中的DbHelperSQL.cs (找自己对应的数据库类型) 修改前20行中的数据库连接字符串获取方式为: //数据库连接字符串(web.config来配置),多数据库可使用Db ...

  4. OpenCV2.4.9 & Visual Studio 2010 环境配置篇

    1. 准备工作 1.1. 安装 Visual Studio 2010, 需要安装 VC++ 相关功能.具体可求助度娘. 1.2. 下载 OpenCV 2.4.9 For Windows:https:/ ...

  5. iOS打包ipa 让别人设备安装你的App

    首先推荐一本书<一步一步学习iOS 5编程(第二版) – PDF 中文版>在一本学习IOS入门很不错的书籍,目前,这是第一本介绍iOS 5.x 和 Xcode 4.3 的中文版书籍,尤其适 ...

  6. Python中%s和%r的区别

    早先使用Python工作的时候,对于格式化输出%s和%r的使用都是混着用的. 这一次就出错了: cu.execute("insert into ipPool values(null, '%r ...

  7. confluence5.8.10的使用

    之前在windows上安装了confluence5.8.10,结果有一天知什么缘故,数据库数据损坏,知识库彻底打不开了,所有的文档都付之东流,真的不是一般心痛.因此考虑将其装到linux机器上,因为t ...

  8. dedecms 文章内容文章名字和文章网址的调用

    文章标题: <a href="{dede:field name='arcurl'/}">{dede:field.title/}</a> 本文章网址: < ...

  9. linux 定时执行shell

    第一步:安装 crontab ,命令 yum -y install vixie-cron                扩展:service crond start //启动服务            ...

  10. 基于Jquery+Ajax+Json实现分页显示

    1.后台action产生json数据. List blackList = blackService.getBlackInfoList(mobileNum, gatewayid, startDate, ...