平衡树:Splaytree POJ 3580 SuperMemo
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了平衡树:Splaytree POJ 3580 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, {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
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的主要内容,如果未能解决你的问题,请参考以下文章