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:这题我交了好多次才AC ~~~
思路其实很简单,主要是程序实现和各种细节给跪了。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int maxn=200010; 6 const int INF=2147483647; 7 int Min[maxn],key[maxn],fa[maxn],ch[maxn][2]; 8 int flip[maxn],add[maxn],sz[maxn],rt,cnt,n,Q; 9 10 void Push_up(int p){ 11 Min[p]=min(key[p],min(Min[ch[p][0]],Min[ch[p][1]])); 12 sz[p]=sz[ch[p][0]]+sz[ch[p][1]]+1; 13 } 14 15 void Add(int p,int d){ 16 if(p){ 17 Min[p]+=d; 18 key[p]+=d; 19 add[p]+=d; 20 } 21 } 22 23 void Flip(int p){ 24 swap(ch[p][0],ch[p][1]); 25 flip[p]^=1; 26 } 27 28 void Push_down(int p){ 29 if(add[p]){ 30 Add(ch[p][0],add[p]); 31 Add(ch[p][1],add[p]); 32 add[p]=0; 33 } 34 if(flip[p]){ 35 Flip(ch[p][0]); 36 Flip(ch[p][1]); 37 flip[p]=0; 38 } 39 } 40 41 void Rotate(int x){ 42 int y=fa[x],g=fa[y],c=ch[y][1]==x; 43 ch[y][c]=ch[x][c^1]; 44 fa[ch[x][c^1]]=y;fa[y]=x; 45 ch[x][c^1]=y;fa[x]=g; 46 if(g) 47 ch[g][ch[g][1]==y]=x; 48 Push_up(y); 49 } 50 51 void Splay(int x,int g=0){ 52 for(int y;(y=fa[x])!=g;Rotate(x)) 53 if(fa[y]!=g) 54 Rotate((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x); 55 Push_up(x); 56 if(!g) 57 rt=x; 58 } 59 60 void Make_root(int x,int g=0){ 61 int p=rt; 62 while(true){ 63 Push_down(p); 64 if(sz[ch[p][0]]+1==x)break; 65 if(sz[ch[p][0]]+1<x){ 66 x-=sz[ch[p][0]]+1; 67 p=ch[p][1]; 68 } 69 else 70 p=ch[p][0]; 71 } 72 Splay(p,g); 73 } 74 75 int Build(int pre,int l,int r){ 76 if(l>r)return 0; 77 int mid=(l+r)>>1; 78 ch[mid][0]=Build(mid,l,mid-1); 79 if(mid>1&&mid<n) 80 scanf("%d",&key[mid]); 81 else 82 key[mid]=INF; 83 Min[mid]=key[mid]; 84 fa[mid]=pre;sz[mid]=1; 85 ch[mid][1]=Build(mid,mid+1,r); 86 Push_up(mid); 87 return mid; 88 } 89 90 int main(){ 91 Min[0]=2147482647; 92 scanf("%d",&n);n+=2; 93 rt=Build(0,1,n);cnt=n; 94 scanf("%d",&Q); 95 char s[10];int a,b,x; 96 while(Q--){ 97 scanf("%s",s); 98 if(!strcmp(s,"ADD")){ 99 scanf("%d%d%d",&a,&b,&x);a++;b++; 100 Make_root(a-1); 101 Make_root(b+1,rt); 102 Push_down(rt); 103 Push_down(ch[rt][1]); 104 Add(ch[ch[rt][1]][0],x); 105 } 106 else if(!strcmp(s,"MIN")){ 107 scanf("%d%d",&a,&b);a++;b++; 108 Make_root(a-1); 109 Make_root(b+1,rt); 110 Push_down(rt); 111 Push_down(ch[rt][1]); 112 printf("%d\n",Min[ch[ch[rt][1]][0]]); 113 } 114 else if(!strcmp(s,"DELETE")){ 115 scanf("%d",&x);x++; 116 Make_root(x-1); 117 Make_root(x+1,rt); 118 ch[ch[rt][1]][0]=0; 119 Push_up(ch[rt][1]); 120 Push_up(rt); 121 } 122 else if(!strcmp(s,"REVERSE")){ 123 scanf("%d%d",&a,&b);a++;b++; 124 Make_root(a-1); 125 Make_root(b+1,rt); 126 Flip(ch[ch[rt][1]][0]); 127 } 128 else if(!strcmp(s,"INSERT")){ 129 scanf("%d%d",&a,&x);a++; 130 Make_root(a); 131 Make_root(a+1,rt); 132 int p=++cnt;sz[p]=1; 133 ch[ch[rt][1]][0]=p; 134 key[p]=Min[p]=x; 135 fa[p]=ch[rt][1]; 136 Push_up(ch[rt][1]); 137 Push_up(rt); 138 } 139 else if(!strcmp(s,"REVOLVE")) 140 { 141 scanf("%d%d%d",&a,&b,&x);a++;b++; 142 Make_root(a-1); 143 Make_root(b+1,rt); 144 x%=b-a+1; 145 if(x){ 146 Make_root(b-x); 147 Make_root(b+1,rt); 148 int tmp=ch[ch[rt][1]][0]; 149 ch[ch[rt][1]][0]=0; 150 Push_up(ch[rt][1]); 151 Push_up(rt); 152 Make_root(a-1); 153 Make_root(a,rt); 154 ch[ch[rt][1]][0]=tmp; 155 fa[tmp]=ch[rt][1]; 156 Push_up(ch[rt][1]); 157 Push_up(rt); 158 } 159 } 160 } 161 return 0; 162 }
时隔多月,我学会了treap,再AC了一遍。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cstdio> 5 using namespace std; 6 const int maxn=200010; 7 const int INF=2147483647; 8 int key[maxn],flip[maxn],add[maxn],cnt,rt; 9 int Min[maxn],sz[maxn],ch[maxn][2],fix[maxn]; 10 int x,y,z,t1,t2; 11 struct Treap{ 12 void Init(){ 13 Min[0]=INF; 14 //srand(time(NULL)); poj上不能在G++上用这个,否则RE 15 } 16 17 int Newnode(int v){ 18 sz[++cnt]=1; 19 Min[cnt]=key[cnt]=v; 20 flip[cnt]=add[cnt]=0; 21 ch[cnt][0]=ch[cnt][1]=0; 22 fix[cnt]=rand(); 23 return cnt; 24 } 25 26 void Push_up(int x){ 27 sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1; 28 Min[x]=min(min(Min[ch[x][0]],Min[ch[x][1]]),key[x]); 29 } 30 31 void Flip(int x){ 32 swap(ch[x][0],ch[x][1]); 33 flip[x]^=1; 34 } 35 36 void Add(int x,int d){ 37 if(!x)return; 38 key[x]+=d; 39 Min[x]+=d; 40 add[x]+=d; 41 } 42 43 void Push_down(int x){ 44 if(add[x]){ 45 Add(ch[x][0],add[x]); 46 Add(ch[x][1],add[x]); 47 add[x]=0; 48 } 49 if(flip[x]){ 50 Flip(ch[x][0]); 51 Flip(ch[x][1]); 52 flip[x]=0; 53 } 54 } 55 56 int Merge(int x,int y){ 57 if(!x||!y)return x|y; 58 Push_down(x); 59 Push_down(y); 60 if(fix[x]<=fix[y]){ 61 ch[x][1]=Merge(ch[x][1],y); 62 Push_up(x); 63 return x; 64 } 65 else{ 66 ch[y][0]=Merge(x,ch[y][0]); 67 Push_up(y); 68 return y; 69 } 70 } 71 72 void Split(int x,int k){ 73 Push_down(x); 74 if(k>sz[x]){t1=x;t2=0;return;} 75 76 if(sz[ch[x][0]]+1==k){ 77 t1=ch[x][0];t2=x; 78 ch[x][0]=0; 79 Push_up(x); 80 return; 81 } 82 83 if(sz[ch[x][0]]+1<k){ 84 k-=sz[ch[x][0]]+1; 85 Split(ch[x][1],k); 86 ch[x][1]=t1;t1=x; 87 Push_up(x); 88 } 89 90 else{ 91 Split(ch[x][0],k); 92 ch[x][0]=t2;t2=x; 93 Push_up(x); 94 } 95 } 96 97 98 void Insert(int k,int v){ 99 Split(rt,k+1); 100 t1=Merge(t1,Newnode(v)); 101 rt=Merge(t1,t2); 102 } 103 104 void Delete(int k){ 105 int tmp; 106 Split(rt,k);tmp=t1; 107 Split(t2,2);t1=tmp; 108 rt=Merge(t1,t2); 109 } 110 111 void Divide(int l,int r){ 112 Split(rt,l);x=t1; 113 Split(t2,r-l+2);y=t1;z=t2; 114 } 115 116 void Converge(){ 117 x=Merge(x,y); 118 rt=Merge(x,z); 119 } 120 121 void Add(int l,int r,int d){ 122 Divide(l,r);Add(y,d); 123 Converge(); 124 } 125 126 void Reverse(int l,int r){ 127 Divide(l,r);Flip(y); 128 Converge(); 129 } 130 131 void Revolve(int l,int r,int k){ 132 Divide(l,r); 133 k%=sz[y]; 134 if(k){ 135 Split(y,sz[y]-k+1); 136 y=Merge(t2,t1); 137 } 138 Converge(); 139 } 140 141 int Query(int l,int r){ 142 Divide(l,r); 143 int ret=Min[y]; 144 Converge(); 145 return ret; 146 } 147 }T; 148 149 int n,Q; 150 char op[10]; 151 152 int main(){ 153 T.Init(); 154 scanf("%d",&n); 155 for(int i=1,a;i<=n;i++){ 156 scanf("%d",&a); 157 T.Insert(i,a); 158 } 159 int l,r,k; 160 scanf("%d",&Q); 161 while(Q--){ 162 scanf("%s",op); 163 if(!strcmp(op,"ADD")){ 164 scanf("%d%d%d",&l,&r,&k); 165 T.Add(l,r,k); 166 } 167 else if(!strcmp(op,"REVERSE")){ 168 scanf("%d%d",&l,&r); 169 T.Reverse(l,r); 170 } 171 else if(!strcmp(op,"REVOLVE")){ 172 scanf("%d%d%d",&l,&r,&k); 173 T.Revolve(l,r,k); 174 } 175 else if(!strcmp(op,"INSERT")){ 176 scanf("%d%d",&l,&k); 177 T.Insert(l,k); 178 } 179 else if(!strcmp(op,"DELETE")){ 180 scanf("%d",&k); 181 T.Delete(k); 182 } 183 else if(!strcmp(op,"MIN")){ 184 scanf("%d%d",&l,&r); 185 printf("%d\n",T.Query(l,r)); 186 } 187 } 188 return 0; 189 }
有些地方没打好,很丑……
决定日后整理为模板。
转载于:https://wwwblogs/TenderRun/p/5203538.html
更多推荐
平衡树(Splay):Splaytree POJ 3580 SuperMemo
发布评论