【POJ3580】【splay版】SuperMemo

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, {A1A2, ... An}. Then the host performs a series of operations and queries on the sequence which consists:

  1. 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}
  2. 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}
  3. REVOLVE x y T: rotate sub-sequence {Ax ... AyT times. For example, performing "REVOLVE 2 4 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 2, 5}
  4. 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}
  5. DELETE x: delete Ax. For example, performing "DELETE 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5}
  6. 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 (≤ 100000).

The following n lines describe the sequence.

Then follows 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

Source

【分析】
真实蛋疼了。。
第一次写的时候居然犯了一个傻逼到极点的错误。。。。
翻转部分不会,是看别人的。不过感觉应该还有不同的写法。
代码写得比较丑,主要是尝试了引用。
  1 #include <iostream>

  2 #include <cstdio>

  3 #include <algorithm>

  4 #include <cstring>

  5 #include <vector>

  6 #include <utility>

  7 #include <iomanip>

  8 #include <string>

  9 #include <cmath>

 10 #include <queue>

 11 #include <assert.h>

 12 #include <map>

 13 #include <ctime>

 14 #include <cstdlib>

 15 #define LOCAL

 16 const int MAXN = 200000 + 10;

 17 const int INF = 100000000;

 18 const int SIZE = 450;

 19 const int maxnode =  0x7fffffff + 10;

 20 using namespace std;

 21 struct SPLAY{

 22        struct Node{

 23               int val, Min;//分别为值,最小值,大小和lazy下标 

 24               int size, lazy;

 25               bool turn;

 26               Node *parent, *ch[2];

 27               

 28               //初始化 

 29               void NEW(int x){

 30                    Min = val = x;

 31                    size = 1;

 32                    lazy = turn = 0;

 33                    parent = ch[0] = ch[1] = NULL;

 34               }

 35               int cmp(){

 36                   if (parent->ch[0] == this) return 0;

 37                   if (parent->ch[1] == this) return 1;

 38               }

 39               //还是不要写在里面了..

 40               /*void pushdown(){

 41                    

 42               } 

 43               void update(){

 44                    size = 1;

 45                    if (x->ch[0] != NULL) size += x->ch[0]->size;

 46                    if (x->ch[1] != NULL) size += x->ch[0]->size;

 47               }     

 48               */    

 49        }mem[MAXN], *root;//mem为静态数组 

 50        int tot;

 51        

 52        int get(Node *&x){return (x == NULL ? 0 : x->size);}

 53        //————————————————————这一部分不能卸载里面 

 54        //更新 

 55        void update(Node *&x){

 56             if (x == NULL) return;

 57             x->size = 1;

 58             x->Min = x->val;

 59             if (x->ch[0] != NULL) {x->Min = min(x->Min, x->ch[0]->Min);x->size += x->ch[0]->size;}

 60             if (x->ch[1] != NULL) {x->Min = min(x->Min, x->ch[1]->Min);x->size += x->ch[1]->size;}

 61        }

 62        void pushdown(Node *&x){//标记下传 

 63             if (x == NULL) return;

 64             if (x->lazy){

 65                int tmp = x->lazy;

 66                x->val += tmp;

 67                if (x->ch[0] != NULL) {x->ch[0]->lazy += tmp;x->ch[0]->Min += tmp;}

 68                if (x->ch[1] != NULL) {x->ch[1]->lazy += tmp;x->ch[1]->Min += tmp;}

 69                x->lazy = 0;

 70             } 

 71             if (x->turn){//翻转

 72                swap(x->ch[0], x->ch[1]);//swap内部用什么实现的呢? 

 73                

 74                if (x->ch[0] != NULL) x->ch[0]->turn ^= 1;

 75                if (x->ch[1] != NULL) x->ch[1]->turn ^= 1; 

 76                x->turn = 0;

 77             }

 78        }

 79        

 80        //———————————————————————————— 

 81        //旋转,1为右旋, 0为左旋

 82        void Rotate(Node *&x, int d){//不用引用也可以 

 83             Node *y = x->parent;

 84             pushdown(y);//注意顺序 

 85             pushdown(x);

 86             pushdown(x->ch[d]);//这个不要忘了

 87             

 88             y->ch[d ^ 1] = x->ch[d];

 89             if (x->ch[d] != NULL) x->ch[d]->parent = y;

 90             x->parent = y->parent;

 91             if (y->parent != NULL){

 92                if (y->parent->ch[0] == y) y->parent->ch[0] = x;

 93                else y->parent->ch[1] = x;

 94             } 

 95             x->ch[d] = y;

 96             y->parent = x;

 97             update(y);

 98             if (y == root) root = x;//如果是引用要小心root被传下去 

 99        } 

100        void debug(){

101             Node *p = new Node;

102             root = new Node;

103             root->ch[1] = p;

104             p->parent = root;

105             printf("%d", p->cmp());

106        }

107        //注意我写的这个跟下午那个不一样,下午那个好麻烦 

108        void splay(Node *&x, Node *&y){

109             pushdown(x);

110             while (x != y){

111                   if(x->parent == y){

112                             if (y->ch[0] == x) Rotate(x, 1);

113                             else Rotate(x,0);

114                             break;

115                   }else{

116                             Node *y = x->parent, *z = y->parent;//注意一定要这样弄一下 

117                             if (z->ch[0] == y)

118                             if (y->ch[0] == x) Rotate(y,1),Rotate(x, 1);

119                             else Rotate(x, 0), Rotate(x, 1); 

120                             else if (y->ch[1] == x) Rotate(y, 0), Rotate(x, 0); 

121                             else Rotate(x, 1), Rotate(x, 0); 

122                             if (z == y) break;

123                   }

124                   update(x);

125             }

126             update(x);

127        }

128        //寻找第k大 

129        void find(Node *&t, int k){

130             int tmp;

131             Node *p = root;

132             while (1){

133                   pushdown(p);

134                   tmp = get(p->ch[0]);

135                   if (k == (tmp + 1)) break;

136                   if (k <= tmp) p = p->ch[0];

137                   else {k -= tmp + 1, p = p->ch[1];}

138             }

139             pushdown(p);

140             splay(p, t);

141        }

142        //插入操作 

143        void Insert(int pos, int val){

144             //还是卡出来 

145             find(root, pos + 1);

146             find(root->ch[1], pos + 2);

147             Node *t = &mem[tot++], *x = root->ch[1];

148             pushdown(root);

149             pushdown(x);

150             t->NEW(val);

151             //直接拆开放中间,放在root->ch[1]->ch[0]应该也可以 

152             t->ch[1] = x;

153             x->parent = t;

154             root->ch[1] = t;

155             t->parent = root;

156             splay(x, root);

157        }

158        //区间加 

159        void Add(int l, int r, int x){

160             find(root, l);

161             find(root->ch[1] , r + 2);

162             Node *t = root->ch[1]->ch[0];

163             pushdown(t);

164             update(t);

165             t->Min += x;

166             t->lazy += x;

167             splay(t, root);

168        }

169        //翻转操作 

170        void Reverse(int l, int r){

171             find(root, l);

172             find(root->ch[1], r + 2);

173             root->ch[1]->ch[0]->turn ^= 1;

174             Node *x = root->ch[1]->ch[0];

175             splay(x, root);

176        }

177        //交换操作,这一段我是看别人的.... 

178        void Revolve(int l, int r, int t){

179             Node *p1, *p2;

180             

181             find(root, l);

182             find(root->ch[1], r + 2);

183             find(root->ch[1]->ch[0], r + 1 - t);

184             

185             p1 = root->ch[1]->ch[0];

186             pushdown(p1);

187             p2 = p1->ch[1];

188             p1->ch[1] = NULL;

189             find(root->ch[1]->ch[0], l + 1);

190             p1 = root->ch[1]->ch[0];

191             pushdown(p1);

192             p1->ch[0] = p2;

193             p2->parent = p1;

194             splay(p2, root);

195        }

196        int getMin(int l, int r){

197             find(root, l);

198             find(root->ch[1], r + 2);

199             Node *x = root->ch[1];

200             pushdown(x);

201             x = x->ch[0];

202             pushdown(x);

203             update(x);

204             return x->Min; 

205        }

206        void Erase(int pos){//删除 

207             find(root, pos);

208             find(root->ch[1], pos + 2);

209             pushdown(root->ch[1]);

210             root->ch[1]->ch[0] = NULL;

211             Node *x = root->ch[1];

212             splay(x, root);

213        }

214        void init(){

215             //注意还要加一个正无穷 

216             tot = 0;

217             root = &mem[tot++];

218             root->NEW(INF);

219             root->ch[1] = &mem[tot++];

220             root->ch[1]->NEW(INF);

221        }

222        void print(Node *t){

223             if (t == NULL) return;

224             print(t->ch[0]);

225             printf("%d ", t->val);

226             if (t->parent != NULL) printf("%d\n", t->parent->val);

227             print(t->ch[1]);

228        }

229 }A;

230 

231 int n, m;

232 //注意在这里为了防止掉到0,所以每个位置都要+1 

233 void init(){//初始化 

234     A.init();

235     scanf("%d", &n);

236     for (int i = 0 ; i < n; i++){

237         int x;

238         scanf("%d", &x);

239         A.Insert(i, x);

240         //printf("%d\n", A.root->val);

241     }

242     //A.print(A.root);

243 }

244 void work(){

245      scanf("%d", &m);

246      for (int i = 1; i <= m; i++){//询问,按顺序来。。 

247            char str[20];

248            scanf("%s", str);

249            if (str[0] == 'A'){

250               int l, r, x;

251               scanf("%d%d%d", &l, &r, &x);

252               A.Add(l, r, x);

253            }else if (str[0] == 'R'){

254               int l, r;

255               scanf("%d%d", &l, &r);

256               if (str[3] == 'E') A.Reverse(l, r);

257               else{

258                    int x, len;

259                    scanf("%d", &x);

260                    len = r - l + 1;

261                    x = (x % len + len) % len;

262                    if (x == 0 || l == r) continue;//我开始居然傻逼的写在前面.... 

263                    A.Revolve(l, r, x);

264               } 

265            }else if (str[0] == 'I'){

266                  int l, x; 

267                  scanf("%d%d", &l, &x);

268                  A.Insert(l, x);

269            }else if (str[0] == 'D'){

270                  int l;

271                  scanf("%d", &l);

272                  A.Erase(l);

273            }else if (str[0] == 'M'){

274                  int l, r;

275                  scanf("%d%d", &l, &r);

276                  printf("%d\n", A.getMin(l, r));

277            }

278      }

279 }

280 void debug(){

281      

282 }

283 

284 int main(){

285     

286     init();

287     work();

288     //debug();

289     //A.debug();

290     return 0;

291 }
View Code

 

你可能感兴趣的:(super)