poj 3580 SuperMemo (Splay)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj 3580 SuperMemo (Splay)相关的知识,希望对你有一定的参考价值。
好恶心的题目,真是各种操作都来了个遍 。。。
不过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)的主要内容,如果未能解决你的问题,请参考以下文章
POJ 3580 - SuperMemo - [伸展树splay]