平衡树:Splaytree POJ 3580 SuperMemo

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了平衡树:Splaytree POJ 3580 SuperMemo相关的知识,希望对你有一定的参考价值。

SuperMemo
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 12788   Accepted: 3986
Case Time Limit: 2000MS

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:这题我交了50次才对 ~~~

  技术分享

  思路其实很简单,主要是程序实现和各种细节。
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 using namespace std;
  7 const int maxn=200010;
  8 const int INF=2147483647;
  9 int Min[maxn],key[maxn],ch[maxn][2],fa[maxn],flip[maxn],Mark[maxn],size[maxn],root,cnt;
 10 
 11 void Push_up(int p)
 12 {
 13     if(!p)return;
 14     Min[p]=min(key[p],min(Min[ch[p][0]],Min[ch[p][1]]));
 15     size[p]=size[ch[p][0]]+size[ch[p][1]]+1;
 16 }
 17 void Add(int p,int d)
 18 {
 19     if(!p)return;
 20     Min[p]+=d;
 21     key[p]+=d;
 22     Mark[p]+=d; 
 23 }
 24 void Flip(int p)
 25 {
 26     if(!p)return;
 27     swap(ch[p][0],ch[p][1]);
 28     flip[p]^=1; 
 29 }
 30 void Push_down(int p)
 31 {
 32     if(Mark[p]){
 33         Add(ch[p][0],Mark[p]);
 34         Add(ch[p][1],Mark[p]);
 35         Mark[p]=0;
 36     }
 37     if(flip[p]){
 38         Flip(ch[p][0]);
 39         Flip(ch[p][1]);
 40         flip[p]=0;
 41     }
 42 }
 43 void Rotate(int x)
 44 {
 45     int y=fa[x],g=fa[y],c=ch[y][1]==x;
 46     ch[y][c]=ch[x][c^1];ch[x][c^1]=y;
 47     fa[ch[y][c]]=y;fa[y]=x;fa[x]=g;
 48     Push_up(y);Push_up(x);
 49     if(g)    
 50         ch[g][ch[g][1]==y]=x;
 51 }
 52 
 53 void Splay(int x,int g=0)
 54 {
 55     for(int y;(y=fa[x])!=g;Rotate(x))
 56         if(fa[y]!=g)
 57             Rotate((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x);
 58     if(g==0)
 59         root=x;        
 60 }
 61 
 62 void Bring_up(int x,int g=0)
 63 {
 64     int p=root;
 65     while(true){
 66         Push_down(p);
 67         if(size[ch[p][0]]+1==x)break;
 68         if(size[ch[p][0]]>=x)
 69             p=ch[p][0];
 70         else{
 71             x-=size[ch[p][0]]+1;
 72             p=ch[p][1];    
 73         }    
 74     }
 75     Splay(p,g);
 76 }
 77 #define Go ch[ch[root][1]][0]
 78 int main()
 79 {
 80     int n,p,l,r,x,Q;
 81     scanf("%d",&n);
 82     Min[0]=INF;size[0]=0;
 83     for(int i=0;i<=n+1;i++)
 84     {
 85         if(i!=0&&i!=n+1)
 86             scanf("%d",&x);
 87         else
 88             x=INF;
 89         p=++cnt;        
 90         key[p]=Min[p]=x;
 91         size[p]=1;
 92         if(root)
 93             ch[root][1]=p,fa[p]=root,Rotate(p);
 94         root=p;    
 95     } 
 96     char s[15];
 97     scanf("%d",&Q);
 98     while(Q--)
 99     {
100         scanf("%s",s);
101         if(!strcmp(s,"MIN")){
102             scanf("%d%d",&l,&r);l++;r++;
103             Bring_up(l-1);
104             Bring_up(r+1,root);
105             Push_down(root);
106             Push_down(ch[root][1]);
107             printf("%d\n",Min[Go]);
108         }
109         else if(!strcmp(s,"ADD")){
110             scanf("%d%d%d",&l,&r,&x);
111             l++;r++;
112             Bring_up(l-1);
113             Bring_up(r+1,root);
114             Add(Go,x);
115             Push_up(ch[root][1]);
116             Push_up(root);
117         }
118         else if(!strcmp(s,"INSERT")){
119             scanf("%d%d",&l,&x);l++;
120             Bring_up(l);
121             Bring_up(l+1,root);
122             Go=++cnt;
123             key[Go]=Min[Go]=x;
124             size[Go]=1;
125             if(root)
126                 fa[Go]=ch[root][1];
127             else
128                 root=Go;    
129             Push_up(ch[root][1]);
130             Push_up(root);
131         }        
132         else if(!strcmp(s,"DELETE")){
133             scanf("%d",&l);l++;
134             Bring_up(l-1);
135             Bring_up(l+1,root);
136             Go=0;
137             Push_up(ch[root][1]);
138             Push_up(root);
139         }
140         else if(!strcmp(s,"REVERSE")){
141             scanf("%d%d",&l,&r);l++;r++;
142             Bring_up(l-1);
143             Bring_up(r+1,root);
144             Flip(Go);
145         }
146         else if(!strcmp(s,"REVOLVE")){
147             scanf("%d%d%d",&l,&r,&x);l++;r++;
148             x%=r-l+1;
149             if(x==0)continue;
150             Bring_up(r-x);
151             Bring_up(r+1,root);
152             int tmp=Go;Go=0;
153             Push_up(ch[root][1]);
154             Push_up(root);
155             Bring_up(l-1);
156             Bring_up(l,root);
157             Go=tmp;fa[Go]=ch[root][1];
158             Push_up(ch[root][1]);
159             Push_up(root);
160         }
161     }
162     return 0;
163 }

 


  


以上是关于平衡树:Splaytree POJ 3580 SuperMemo的主要内容,如果未能解决你的问题,请参考以下文章

poj 3580 SuperMemo (Splay)

二叉平衡树的实现(c语言编程)

[POJ3580]SuperMemo

Poj 3580-SuperMemo Splay

POJ3580:SuperMemo

POJ3580 SuperMemo