poj 3580 SuperMemo (Splay)

Posted

tags:

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

poj 3580

好恶心的题目,真是各种操作都来了个遍 。。。

不过Splay树真是一种神奇的东西,通过旋转就能实现各种操作,而且方法也都相差不大 。

题意:

  给出一个数字序列,有6种操作:

    (1) ADD x y d: 第x个数到第y个数加d 。

    (2) REVERSE x y : 将区间[x,y]中的数翻转 。 

    (3) REVOLVE x y t :将区间[x,y]旋转t次,如1 2 3 4 5 旋转2次后就变成4 5 1 2 3 。

    (4) INSERT x p :在第x个数后面插入p 。

    (5)DELETE x :删除第x个数 。

    (6) MIN x y : 查询区间[x,y]中的最小值 。

解法:

  关于第三点,一开始想难道是一个数一个数从后面取出放到最前面?但这样复杂度太大 。后来仔细一想,既然一个数一个数弄可以,为啥不直接切出一个区间放到最前面呢,然后,就没有然后了 。。。

  注意t可能很大,所以要先取模 。(至于有没有可能出现负数,我是没试过,反正做了处理就是了 。。。)

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cmath>
  5 #include <cstring>
  6 #include <queue>
  7 #include <set>
  8 #include <vector>
  9 #include <map>
 10 #define ll long long
 11 
 12 using namespace std;
 13 
 14 const int N=200000+7;
 15 const int INF=0x3f3f3f3f;
 16 
 17 struct tree{
 18     int key,size,fa,MIN,add,son[2];
 19     bool flag;
 20 }t[N];
 21 int tot,root;
 22 
 23 
 24 inline void vis(int x){  // Debug
 25     if (!x) return;
 26     printf("节点:%2d : 左儿子 %2d 右儿子 %2d  key值 %2d  size值 %2d filp: %d\n",x,t[x].son[0],t[x].son[1],t[x].key,t[x].size,t[x].flag);
 27     printf("节点:%2d : 最小值 %2d \n",x,t[x].MIN);
 28     vis(t[x].son[0]);
 29     vis(t[x].son[1]);
 30 }
 31 
 32 int A[N];
 33 int n;
 34 
 35 inline void pushup(int x){
 36     t[x].size=t[t[x].son[0]].size+t[t[x].son[1]].size+1;
 37     t[x].MIN=t[x].key;
 38     if (t[x].son[0]) 
 39         t[x].MIN=min(t[x].MIN,t[t[x].son[0]].MIN);
 40     if (t[x].son[1])
 41         t[x].MIN=min(t[x].MIN,t[t[x].son[1]].MIN);
 42 }
 43 
 44 inline void pushdown(int x){
 45     if (t[x].flag){
 46         t[x].flag=false;
 47         swap(t[x].son[0],t[x].son[1]);
 48         t[t[x].son[0]].flag^=1;
 49         t[t[x].son[1]].flag^=1;
 50     }
 51 
 52     if (t[x].add>0){
 53         if (t[x].son[0]){
 54             t[t[x].son[0]].key+=t[x].add;
 55             t[t[x].son[0]].add+=t[x].add;
 56             t[t[x].son[0]].MIN+=t[x].add;
 57         }
 58         if (t[x].son[1]){
 59             t[t[x].son[1]].key+=t[x].add;
 60             t[t[x].son[1]].add+=t[x].add;
 61             t[t[x].son[1]].MIN+=t[x].add;
 62         }
 63         t[x].add=0;
 64     }
 65 }
 66 
 67 inline void rotate(int x,int p){
 68     int y=t[x].fa;
 69     pushdown(y);
 70     pushdown(x);
 71     t[y].son[!p]=t[x].son[p];
 72     t[t[x].son[p]].fa=y;
 73     t[x].fa=t[y].fa;
 74     if (t[x].fa)
 75         t[t[x].fa].son[t[t[x].fa].son[1]==y]=x;
 76     t[x].son[p]=y;
 77     t[y].fa=x;
 78     pushup(y);
 79     pushup(x);
 80 }
 81 
 82 inline void Splay(int x,int to){
 83     while (t[x].fa!=to){
 84         if (t[t[x].fa].fa==to)
 85             rotate(x,t[t[x].fa].son[0]==x);
 86         else {
 87             int y=t[x].fa,z=t[y].fa;
 88             int p=(t[z].son[0]==y);
 89             if (t[y].son[p]==x)
 90                 rotate(x,!p),rotate(x,p);
 91             else 
 92                 rotate(y,p),rotate(x,p);
 93         }
 94     }
 95     if (to==0) root=x;
 96 }
 97 
 98 inline int newnode(int key,int fa){
 99     ++tot;
100     t[tot].key=key;
101     t[tot].fa=fa;
102     t[tot].size=1;
103     t[tot].MIN=key;
104     t[tot].add=0;
105     t[tot].flag=false;
106     t[tot].son[0]=t[tot].son[1]=0;
107     return tot;
108 }
109 
110 inline int get_kth(int k){
111     int x=root;
112     for(;;){
113         pushdown(x);
114         if (k==t[t[x].son[0]].size+1)
115             break;
116         if (k>t[t[x].son[0]].size+1){
117             k-=t[t[x].son[0]].size+1;
118             x=t[x].son[1];
119         }
120         else 
121             x=t[x].son[0];
122     }
123     return x;
124 }
125 
126 inline int bulidtree(int L,int R,int fa){
127     if (L>R) return 0;
128 
129     int mid=(L+R)>>1,x;
130     x=newnode(A[mid],fa);
131     t[x].son[0]=bulidtree(L,mid-1,x);
132     t[x].son[1]=bulidtree(mid+1,R,x);
133     pushup(x);
134 
135     return x;
136 }
137 
138 inline void add(int L,int R,int d){
139     L=get_kth(L);
140     R=get_kth(R+2);
141     Splay(L,0);
142     Splay(R,L);    
143     t[t[R].son[0]].key+=d;
144     t[t[R].son[0]].MIN+=d;
145     t[t[R].son[0]].add+=d;
146     pushup(R);
147     pushup(L);
148 }
149 
150 inline void reverse(int L,int R){
151     L=get_kth(L);
152     R=get_kth(R+2);
153     Splay(L,0);
154     Splay(R,L);
155     t[t[R].son[0]].flag^=1;
156 }
157 
158 inline void revolve(int L,int R,int k){
159     k=(k%(R-L+1)+(R-L+1))%(R-L+1);
160     if (!k) return;
161 
162     int x=get_kth(R-k+1);
163     int y=get_kth(R+2);
164     Splay(x,0);
165     Splay(y,x);
166     int tmp=t[y].son[0];
167     t[y].son[0]=0; 
168     pushup(y);
169     pushup(x);
170 
171     x=get_kth(L);
172     y=get_kth(L+1);
173     Splay(x,0);
174     Splay(y,x);
175     t[y].son[0]=tmp;
176     t[tmp].fa=y;
177     pushup(y);
178     pushup(x);
179 }
180 
181 inline void insert(int x,int p){
182     Splay(get_kth(x+1),0);
183     Splay(get_kth(x+2),root);
184     t[t[root].son[1]].son[0]=newnode(p,t[root].son[1]);
185     pushup(t[root].son[1]);
186     pushup(root);
187 }
188 
189 inline void del(int x){
190     Splay(get_kth(x),0);
191     Splay(get_kth(x+2),root);
192     t[t[root].son[1]].son[0]=0;
193     pushup(t[root].son[1]);
194     pushup(root);
195 }
196 
197 inline int query(int L,int R){
198     int x=get_kth(L);
199     int y=get_kth(R+2);
200     Splay(x,0);
201     Splay(y,x);
202     return t[t[y].son[0]].MIN;
203 }
204 
205 int main(){
206     scanf("%d",&n);
207     for (int i=1;i<=n;i++) scanf("%d",&A[i]);
208     A[0]=A[n+1]=INF;
209 
210     root=bulidtree(0,n+1,0);
211     // 由于取点的时候很多是取该点的前一个点或者后一个点,所以要加多两个虚节点
212 
213     int m,x,y,z;
214     char ch[20];
215     scanf("%d",&m);
216     while (m--){
217         scanf("%s",ch);
218         switch (ch[0]){
219             case A:
220                 scanf("%d %d %d",&x,&y,&z);
221                 add(x,y,z);
222                 break;
223             case R:
224                 if (ch[3]==E) {
225                     scanf("%d %d",&x,&y);
226                     reverse(x,y);
227                 }
228                 else {
229                     scanf("%d %d %d",&x,&y,&z);
230                     revolve(x,y,z);
231                 }
232                 break;
233             case I:
234                 scanf("%d %d",&x,&y);
235                 insert(x,y);
236                 break;
237             case D:
238                 scanf("%d",&x);
239                 del(x);
240                 break;
241             case M:
242                 scanf("%d %d",&x,&y);
243                 printf("%d\n",query(x,y));
244                 break;
245         }
246     }
247 
248     return 0;
249 }

 

以上是关于poj 3580 SuperMemo (Splay)的主要内容,如果未能解决你的问题,请参考以下文章

POJ3580:SuperMemo

POJ 3580 - SuperMemo - [伸展树splay]

POJ3580 SuperMemo

平衡树:Splaytree POJ 3580 SuperMemo

POJ 3580SuperMemo

POJ 3580.SuperMemo