POJ 3580——SuperMemo(Splay树,经典题)
来源:互联网 发布:批量编辑图片的软件 编辑:程序博客网 时间:2024/06/13 22:34
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
51 2 3 4 52ADD 2 4 1MIN 4 5
Sample Output
5
—————————————————————分割线——————————————
题目大意:
对一个序列进行7种操作:
区间操作:
(1):ADD x y D 对一段区间都增加一个值value
(2):REVERSE x y 翻转一个区间
(3):REVOLVE x y T 对一个区间向右移动T步(转化成交换两个相邻的区间)
(4):INSERT x P 插入一段区间
(5):DELETE x 删除一段区间
(6):MIN x y 返回一段区间的最小值
思路:
对于右移操作就是讲一段区间分割成两半,然后再合并
[x,a][a+1,y],先将a-1旋转到根,再将a+1旋转到根的右儿子,然后把右儿子的左子树割下来,再将y旋转到根,y+1旋转到根的右儿子,最后将被割下来的子树链接到y+1
注意点:
maxn定义成100001会TL!!!
#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#define Key_value ch[ch[root][1]][0]#define REP(i,n) for(int i=0;i<(n);++i)const int INF=1<<30;const int maxn=100010;using namespace std;int root,tot1,ch[maxn][2],key[maxn],Min[maxn],pre[maxn];int s[maxn],tot2;int rev[maxn],add[maxn],size[maxn];int a[maxn];int n,q;void update_rev(int rt){ if(!rt) return ; swap(ch[rt][0],ch[rt][1]); rev[rt]^=1;}void update_add(int rt,int d){ if(!rt) return ; key[rt]+=d; add[rt]+=d; Min[rt]+=d;}void push_up(int rt){ int lson=ch[rt][0],rson=ch[rt][1]; size[rt]=size[lson]+size[rson]+1; Min[rt]=min(key[rt],min(Min[lson],Min[rson]));}void push_down(int rt){ int lson=ch[rt][0],rson=ch[rt][1]; if(add[rt]) { update_add(lson,add[rt]); update_add(rson,add[rt]); add[rt]=0; } if(rev[rt]) { update_rev(lson); update_rev(rson); rev[rt]=0; }}void NewNode(int &rt,int f,int k){ if(tot2) rt=s[tot2--]; else rt=++tot1; ch[rt][0]=ch[rt][1]=0; pre[rt]=f; key[rt]=k; size[rt]=1; add[rt]=rev[rt]=0; Min[rt]=k;}void build(int &rt,int l,int r,int f){ if(l>r) return ; int mid=(l+r)>>1; NewNode(rt,f,a[mid]); build(ch[rt][0],l,mid-1,rt); build(ch[rt][1],mid+1,r,rt); push_up(rt);}void Init(){ root=tot1=tot2=0; rev[root]=add[root]=ch[root][0]=ch[root][1]=pre[root]=size[root]=0; Min[root]=INF; NewNode(root,0,-1); NewNode(ch[root][1],root,-1); REP(i,n) scanf("%d",&a[i]); build(Key_value,0,n-1,ch[root][1]); push_up(ch[root][1]); push_up(root);}void Rotate(int x,int kind){ int y=pre[x]; push_down(y); push_down(x); ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y]; pre[y]=x; ch[x][kind]=y; push_up(y);}void Splay(int x,int goal){ push_down(x); while(pre[x]!=goal) { if(pre[pre[x]]==goal) { Rotate(x,ch[pre[x]][0]==x); } else { int y=pre[x]; int kind=ch[pre[y]][0]==y; if(ch[y][kind]==x) { Rotate(x,!kind); Rotate(x,kind); } else { Rotate(y,kind); Rotate(x,kind); } } } push_up(x); if(goal==0) root=x;}int Get_kth(int rt,int k){ push_down(rt); int z=size[ch[rt][0]]+1; if(z==k) return rt; if(z>k) return Get_kth(ch[rt][0],k); else return Get_kth(ch[rt][1],k-z);}void Add(int x,int y,int d){ Splay(Get_kth(root,x),0); Splay(Get_kth(root,y+2),root); update_add(Key_value,d); push_up(ch[root][1]); push_up(root);}void Reverse(int x,int y){ Splay(Get_kth(root,x),0); Splay(Get_kth(root,y+2),root); update_rev(Key_value);}void Revolve(int x,int y,int k){ if(!k) return ; int l=y-x+1; l=y-(k%l+l)%l; Splay(Get_kth(root,x),0); Splay(Get_kth(root,l+2),root); int tmp=Key_value; Key_value=0;// pre[Key_value]=0; push_up(ch[root][1]); push_up(root); Splay(Get_kth(root,y-l+x),0); Splay(Get_kth(root,y-l+x+1),root); Key_value=tmp; pre[Key_value]=ch[root][1]; push_up(ch[root][1]); push_up(root);}void Insert(int x,int v){ Splay(Get_kth(root,x+1),0); Splay(Get_kth(root,x+2),root); NewNode(Key_value,ch[root][1],v); push_up(ch[root][1]); push_up(root);}void erase(int rt){ if(!rt) return ; s[++tot2]=rt; erase(ch[rt][0]); erase(ch[rt][1]);}void Delete(int x){ Splay(Get_kth(root,x),0); Splay(Get_kth(root,x+2),root); erase(Key_value); pre[Key_value]=0; Key_value=0; push_up(ch[root][1]); push_up(root);}int Get_answer(int x,int y){ Splay(Get_kth(root,x),0); Splay(Get_kth(root,y+2),root); return Min[Key_value];}int main(){ while(scanf("%d",&n)!=EOF){ Init();scanf("%d",&q);char str[10];int l,r,k;while(q--){scanf("%s",str);if(!strcmp(str,"ADD")){scanf("%d%d%d",&l,&r,&k);Add(l,r,k);}else if(!strcmp(str,"REVERSE")){scanf("%d%d",&l,&r);Reverse(l,r);}else if(!strcmp(str,"REVOLVE")){scanf("%d%d%d",&l,&r,&k);Revolve(l,r,k);}else if(!strcmp(str,"INSERT")){scanf("%d%d",&l,&k);Insert(l,k);}else if(!strcmp(str,"DELETE")){scanf("%d",&l);Delete(l);}else{scanf("%d%d",&l,&r);printf("%d\n",Get_answer(l,r));}}}return 0;}
- POJ 3580——SuperMemo(Splay树,经典题)
- Splay树(多操作)——POJ 3580 SuperMemo
- poj 3580 SuperMemo splay树模板题
- POJ-3580 SuperMemo(Splay树)
- POJ 3580 SuperMemo(Splay树)
- POJ 3580 SuperMemo (Splay)
- splay POJ 3580SuperMemo
- POJ 3580 SuperMemo(Splay)
- POJ 3580 SuperMemo(Splay)
- poj 3580 SuperMemo(Splay)
- poj-3580-SuperMemo-splay
- 【POJ】3580 SuperMemo 【splay】
- POJ 3580 SuperMemo Splay
- POJ 3580 SuperMemo [Splay]
- poj 3580 SuperMemo(伸展树splay)
- BZOJ 1895 & POJ 3580 supermemo (splay)
- POJ 3580 SuperMemo (Splay tree)
- POJ 3580 SuperMemo (SPLAY TREE)
- Dom获取元素的几种方式
- 循环队列 链式队列 的jJAVA实现
- 学习swift资源汇总
- 利用原生JavaScript获取样式的方式小结
- 数据结构与算法分析的C++描述结构学习(2)
- POJ 3580——SuperMemo(Splay树,经典题)
- 10-30
- <六>读<<大话设计模式>>之原型模式
- 用Javascript获取页面元素的位置
- 抽象类和接口比较
- PHP get请求和post请求
- CodeVs 2833 奇怪的梦境
- linux重定向总结
- mysql 主从同步原理