POJ 3580 SuperMemo

  http://poj.org/problem?id=3580

  题目大意说给你一个数列,有区间同加一个数、区间翻转操作、区间滚动操作、删除一个数、插入一个数,查询区间最小值这些操作。

  我是使用Splay乱搞的。其中revolve操作有点头疼,不过仔细观察发现,revolve l r x 其实就是交换(l,r-x)和(r-x+1,r)两个区间。

  代码很长很长很长……而且跟QZ的很像很像很像……

  

  1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <cstdlib>
5 #include <cmath>
6 #define INF ~0u>>1
7 #define NIL SPLAY
8 #define MN 200005
9 using namespace std;
10
11 int n,m,l,r,x,pos;
12 char s[10];
13
14 struct SPLAYTREE{
15 struct NODE{
16 int key,minv,size,add;
17 bool rev;
18 NODE *left,*right,*father;
19 NODE (){}
20 NODE(int _key):key(_key){minv=_key,size=1,add=0,rev=false;}
21 }SPLAY[MN],*SP,*root,*head,*tail;
22
23 void init(){
24 SP=NIL;
25 NIL->key=NIL->minv=INF,NIL->size=0;
26 NIL->left=NIL->right=NIL->father=NIL;
27 head=new(++SP)NODE(INF);
28 head->left=head->right=head->father=NIL;
29 tail=new(++SP)NODE(INF);
30 tail->left=tail->right=tail->father=NIL;
31 head->right=tail,tail->father=head,head->size++;
32 root=head;
33 }
34
35 void pushdown(NODE *&t){
36 if(t->rev){
37 swap(t->left,t->right);
38 t->left->rev=!t->left->rev;
39 t->right->rev=!t->right->rev;
40 t->rev=false;
41 }
42 if(t->add){
43 if(t->left!=NIL){
44 t->left->key+=t->add;
45 t->left->minv+=t->add;
46 t->left->add+=t->add;
47 }
48 if(t->right!=NIL){
49 t->right->key+=t->add;
50 t->right->minv+=t->add;
51 t->right->add+=t->add;
52 }
53 t->add=0;
54 }
55 }
56
57 void update(NODE *&t){
58 t->size=t->left->size+t->right->size+1;
59 t->minv=min(t->key,min(t->left->minv,t->right->minv));
60 }
61
62 void zig(NODE *&t){
63 NODE *f=t->father,*r=t->right;
64 pushdown(f->right);
65 pushdown(t->left);
66 pushdown(t->right);
67 t->father=f->father;
68 if(f==root) root=t;
69 else{
70 if(f->father->left==f) f->father->left=t;
71 else f->father->right=t;
72 }
73 t->right=f,r->father=f,f->father=t,f->left=r;
74 update(f);update(t);
75 }
76
77 void zag(NODE *&t){
78 NODE *f=t->father,*l=t->left;
79 pushdown(f->left);
80 pushdown(t->left);
81 pushdown(t->right);
82 t->father=f->father;
83 if(f==root) root=t;
84 else{
85 if(f->father->left==f) f->father->left=t;
86 else f->father->right=t;
87 }
88 t->left=f,l->father=f,f->father=t,f->right=l;
89 update(f);update(t);
90 }
91
92 void splay(NODE *&root,NODE *&t){
93 pushdown(t);
94 while(root!=t){
95 if(t->father==root){
96 if(t->father->left==t) zig(t);
97 else zag(t);
98 }
99 else{
100 if(t->father->father->left==t->father){
101 if(t->father->left==t) zig(t->father),zig(t);
102 else zag(t),zig(t);
103 }else{
104 if(t->father->left==t) zig(t),zag(t);
105 else zag(t->father),zag(t);
106 }
107 }
108 }
109 }
110
111 void insert(int key,int pos){
112 NODE *t=new(++SP)NODE(key);
113 t->left=t->right=t->father=NIL;
114 NODE *r=root,*p;
115 bool flag=false;
116 while(pushdown(r),r!=NIL){
117 p=r,r->size++;
118 if(r->left->size+1>pos)r=r->left,flag=false;
119 else pos-=r->left->size+1,r=r->right,flag=true;
120 }
121 if(flag) p->right=t;
122 else p->left=t;
123 t->father=p;
124 splay(root,t);
125 }
126
127 void select(NODE *&root,int pos){
128 NODE *r=root;
129 while(pushdown(r),r->left->size+1!=pos){
130 if(r->left->size+1>pos) r=r->left;
131 else pos-=r->left->size+1,r=r->right;
132 }
133 splay(root,r);
134 }
135
136 void remove(int pos){
137 select(root,pos);
138 if(root->left==NIL) root=root->right;
139 else if(root->right==NIL) root=root->left;
140 else{
141 select(root->left,root->left->size);
142 root->left->right=root->right;
143 root->right->father=root->left;
144 root=root->left;
145 }
146 root->father=NIL;
147 update(root);
148 }
149
150 void plus(int l,int r,int a){
151 select(root,l);
152 select(root->right,r-l);
153 NODE *t=root->right->left;
154 t->add+=a,t->key+=a,t->minv+=a;
155 splay(root,t);
156 }
157
158 void reverse(int l,int r){
159 select(root,l);
160 select(root->right,r-l);
161 NODE *t=root->right->left;
162 t->rev=!t->rev;
163 splay(root,t);
164 }
165
166 void revolve(int l,int r,int a){
167 select(root,l);
168 select(root->right,r-l);
169 select(root->right->left,root->right->left->size-a);
170 select(root->right->left->right,root->right->left->right->size);
171 NODE *p=root->right->left,*t=root->right->left->right;
172 p->right=NIL;
173 p->father->left=t,t->father=p->father;
174 t->right=p,p->father=t;
175 update(t);update(p);
176 splay(root,p);
177 }
178
179 int query(int l,int r){
180 select(root,l);
181 select(root->right,r-l);
182 return root->right->left->minv;
183 }
184 }tree;
185
186 int main(){
187 tree.init();
188 scanf("%d",&n);
189 for(int i=1;i<=n;i++){
190 scanf("%d",&x);
191 tree.insert(x,i);
192 }
193
194 scanf("%d",&m);getchar();
195 while(m--){
196 scanf("%s",s);
197 switch(s[0]){
198 case 'A':
199 scanf("%d%d%d",&l,&r,&x);
200 tree.plus(l,r+2,x);
201 break;
202 case 'I':
203 scanf("%d%d",&pos,&x);
204 tree.insert(x,pos+1);
205 break;
206 case 'D':
207 scanf("%d",&pos);
208 tree.remove(pos+1);
209 break;
210 case 'M':
211 scanf("%d%d",&l,&r);
212 printf("%d\n",tree.query(l,r+2));
213 break;
214 case 'R':
215 if(s[3]=='E'){
216 scanf("%d%d",&l,&r);
217 tree.reverse(l,r+2);
218 }else{
219 scanf("%d%d%d",&l,&r,&x);
220 if(x%(r-l+1)) tree.revolve(l,r+2,x%(r-l+1));
221 }
222 break;
223 }
224 getchar();
225 }
226 return 0;
227 }

  

posted @ 2011-07-26 11:23  Delostik  阅读(793)  评论(0编辑  收藏  举报