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

  1. 5
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 2
  8. ADD 2 4 1
  9. MIN 4 5

Sample Output

  1. 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 = + ;
  17. const int INF = 0x7fffffff;
  18. const int SIZE = ;
  19. using namespace std;
  20. struct Node{
  21. int shu[SIZE + ];
  22. int Min, addn, size;//块内最小值,需要加的n
  23. Node *l, *r;
  24. bool turn, add;//turn为翻转标记,add为增加标记
  25.  
  26. Node(){
  27. Min = INF; addn = size = ;
  28. l = r = NULL;
  29. turn = add = ;
  30. }
  31. void update(){
  32. if (turn){
  33. for (int i = ; i <= (size>>); i++) swap(shu[i], shu[size - i + ]);
  34. turn = ;
  35. }
  36. if (add){
  37. add = ;
  38. for (int i = ; i <= size; i++) shu[i] += addn;
  39. Min += addn;
  40. addn = ;
  41. }
  42. }
  43. //统计最小值
  44. void Count(){
  45. update();
  46. Min = INF;
  47. for (int i = ; i <= size; i++) Min = min(shu[i], Min);
  48. }
  49. };
  50. struct Block{
  51. Node *head, *p;
  52. int dir;//剩余的位置
  53.  
  54. Block(){head = new Node;}
  55. //分裂p块
  56. Node *split(Node *&t, int x){//从p的x位置开始分裂
  57. t->update();
  58. Node *p2 = new Node;
  59. p2->r = t->r;
  60. p2->l = t;
  61. if (t->r != NULL) t->r->l = p2;
  62. t->r = p2;
  63. //[1,x]分到p中,[x+1,p->size]在p2中
  64. memcpy(&p2->shu[], &t->shu[x + ], sizeof(int) * (t->size - x));
  65. p2->size = t->size - x;//第一次写反了QAQ
  66. t->size = x;
  67.  
  68. t->Count();
  69. p2->Count();
  70. return p2;
  71. }
  72. Node *merge(Node *a, Node *b){
  73. a->update();
  74. b->update();
  75. Node *t = new Node;
  76. t->r = b->r;
  77. t->l = a->l;
  78. if (b->r != NULL) b->r->l = t;
  79. if (a->l != NULL) a->l->r = t;
  80. t->size = a->size + b->size;
  81. memcpy(&t->shu[], &a->shu[], sizeof(int) * (a->size));
  82. memcpy(&t->shu[a->size + ], &b->shu[], sizeof(int) * (b->size));
  83. t->Count();
  84. if (a->l == NULL)//说明是head
  85. head = t;
  86. delete a;
  87. delete b;
  88. return t;
  89. }
  90. void find(int x){
  91. //路径压缩
  92. int cnt = ;
  93. p = head;
  94. while (cnt + p->size < x){
  95. cnt += p->size;
  96. //if ((p->l != NULL) && (p->l->size + p->size <= (SIZE>>1)))
  97. //p = merge(p->l, p);
  98. if (p->size == && p != head){//删除空白块
  99. p = p->l;
  100. if (p->r != NULL) p->r = p->r->r;
  101. else p->r = NULL;
  102. if (p->r != NULL) p->r->l = p;
  103. }
  104. p = p->r;
  105. }
  106. dir = x - cnt;//注意这个值是直接在pos数组中的
  107. }
  108. //在pos位置插入num个数
  109. void Insert(int pos, int num, int *data){
  110. Node *p2;
  111. find(pos);
  112. if (pos == && head->size == ) goto w;
  113. p->update();
  114. //需要分裂
  115. if (dir != p->size) {
  116. p = split(p, dir);
  117. p = p->l;
  118. p = split(p, p->size);
  119. }else p = split(p, dir);
  120.  
  121. w:int i = ;
  122. while (i <= num){
  123. int tmp = min(SIZE - p->size, num - i + );
  124. memcpy(&p->shu[p->size + ], &data[i], sizeof(int) * (tmp));
  125. p->size += tmp;
  126. i += tmp;
  127. if (num >= i){
  128. p->Count();
  129. p = split(p, p->size);
  130. }
  131. }
  132. p->Count();
  133. }
  134. void Delete(int pos, int num){//从pos位置开始删除num个数字
  135. find(pos);
  136. Node *p2;
  137. while (num > ){
  138. if ((dir == ) && (num >= p->size)){
  139. num -= p->size;
  140. if (p->l != NULL) p->l->r = p->r;
  141. else head = p->r;
  142. if (p->r != NULL) p->r->l = p->l;
  143. p2 = p;
  144. p = p->r;
  145. delete p2;
  146. }else{//不然就暴力删除
  147. p->update();
  148. int tmp = min(dir + num - , p->size);
  149. num -= tmp - dir + ;
  150. for (int i = ; i <= p->size - tmp; i++) p->shu[dir + i - ] = p->shu[tmp + i];
  151. p->size -= tmp - dir + ;
  152. p->Count();
  153. p = p->r;
  154. dir = ;
  155. }
  156. }
  157. if (head == NULL) {head = new Node;}
  158. }
  159. //从pos位置开始给num个数字加上val
  160. void add(int pos, int num, int val){
  161. find(pos);
  162. while (num > ){
  163. if ((dir == ) && (num >= p->size)){
  164. //p->update();
  165. num -= p->size;
  166. p->add = ;
  167. p->addn += val;
  168. p = p->r;
  169. }else{
  170. //打标记好像没必要update?
  171. p->update();//会反转啊
  172. int tmp = min(dir + num - , p->size);
  173. num -= tmp - dir + ;
  174. for (int i = ; i <= tmp - dir; i++) p->shu[i + dir] += val;
  175. p->Count();
  176. p = p->r;
  177. dir = ;
  178. }
  179. }
  180. }
  181. int getMin(int pos, int num){
  182. int Ans = INF;
  183. find(pos);
  184. while (num > ){
  185. if ((dir == ) && (num >= p->size)){
  186. p->Count();
  187. num -= p->size;
  188. Ans = min(Ans, p->Min);
  189. p = p->r;
  190. }else{//暴力判断
  191. p->Count();
  192. int tmp = min(dir + num - , p->size);
  193. num -= tmp - dir + ;
  194. for (int i = ; i <= tmp - dir; i++) Ans = min(p->shu[i + dir], Ans);
  195. p = p->r;
  196. dir = ;
  197. }
  198. }
  199. return Ans;
  200. }
  201. //翻转
  202. void Reverse(int pos, int num){
  203. Node *ap, *bp, *cp, *dp;
  204. Node *p2;
  205. find(pos);
  206. if (p->size >= dir + num - ){
  207. p->update();
  208. for (int i = ; i <= (num>>); i++)
  209. swap(p->shu[dir + i - ], p->shu[num - i + dir]);
  210. //p->Count();这样不会改变Min,不用改!
  211. return;
  212. }
  213. if (dir > ){
  214. num -= p->size - dir + ;
  215. p2 = split(p, dir - );
  216. ap = p2->l;
  217. bp = p2;
  218. p = p2->r;
  219.  
  220. }else{//不然的话dir在一个整块上,
  221. ap = p->l;
  222. bp = p;
  223. }
  224. while (num > p->size){
  225. num -= p->size;
  226. p = p->r;
  227. }
  228.  
  229. //最后一块切割
  230. if (num != p->size){
  231. p2 = split(p, num);
  232. cp = p2->l;
  233. dp = p2;
  234. }else{
  235. cp = p;
  236. dp = p->r;
  237. }
  238. p = bp;
  239. while (){
  240. swap(p->l, p->r);
  241. p->turn = !p->turn;
  242. if (p == cp) break;
  243. p = p->l;
  244. }
  245. //大调换
  246. if (dp != NULL) dp->l = bp;
  247. bp->r = dp;
  248. cp->l = ap;
  249. if (ap != NULL) ap->r= cp;
  250. else head = cp;
  251. }
  252. //旋转
  253. //将[a,b]和[b+1, c]调换
  254. void Revolve(int a, int b, int c){
  255. if (b == c) return;
  256. Node *z[], *y[];
  257. Node *p2;
  258. int L = c - a + ;//总长度
  259. int L2 = b - a + ;//[a,b]的长度
  260. find(a);
  261. int num = L2;
  262. //全部在一个块内
  263. if (p->size >= dir + L - ){
  264. int tmp[SIZE], cnt = ;
  265. for (int i = dir + L2; i <= dir + L - ; i++) tmp[cnt++] = p->shu[i];
  266. for (int i = dir; i <= dir + L2 - ; i++) tmp[cnt++] = p->shu[i];
  267. for (int i = dir; i <= dir + L - ; i++) p->shu[i] = tmp[i - dir + ];
  268. return;
  269. }
  270. //分割第一块
  271. if (dir > ){
  272. num -= p->size - dir + ;
  273. p2 = split(p, dir - );
  274. z[] = p2->l;
  275. y[] = p2;
  276. p = p2->r;
  277. }else{
  278. z[] = p->l;
  279. y[] = p;
  280. }
  281. //中间的这一块
  282. //num = L2;
  283. while (num > p->size){
  284. num -= p->size;
  285. p = p->r;
  286. }
  287. int tmp = num;
  288. num = L - L2;
  289. if (tmp == p->size){
  290. z[] = p;
  291. y[] = p->r;
  292. p = p->r;//这里还要走
  293. }else if(tmp == ){
  294. z[] = p->l;
  295. y[] = p;
  296. }else{
  297. // num -= p->size - tmp;
  298. p2 = split(p, tmp);
  299. z[] = p2->l;
  300. y[] = p2;
  301. p = p2;
  302. }
  303.  
  304. while (num > p->size){
  305. num -= p->size;
  306. p = p->r;
  307. }
  308.  
  309. if (num == p->size){
  310. z[] = p;
  311. y[] = p->r;
  312. }else if (num == ){
  313. z[] = p->l;
  314. y[] = p;
  315. }else{
  316. p2 = split(p, num);
  317. z[] = p2->l;
  318. y[] = p2;
  319. }
  320. //大调换!
  321. if (z[] != NULL) z[]->r = y[];
  322. else head = y[];y[]->l = z[];
  323. if (y[] != NULL) y[]->l = z[];z[]->r = y[];
  324. z[]->r = y[];
  325. y[]->l = z[];
  326. }
  327. void print(){
  328. Node *cur = head;
  329. while (){
  330. if (cur == NULL) break;
  331. cur->update();
  332. for (int i = ; i <= cur->size; i++) printf("%d ", cur->shu[i]);
  333. cur = cur->r;
  334. }
  335. }
  336. }A;
  337. int n, data[MAXN];
  338. char str[];
  339.  
  340. void debug();
  341. void init(){
  342. scanf("%d", &n);
  343. for (int i = ; i <= n; i++) scanf("%d", &data[i]);
  344. A.Insert(, n, data);
  345. }
  346. void work(){
  347. //tot为数字总述
  348. int m, tot = n;
  349. scanf("%d", &m);
  350. for (int i = ; i <= m; i++){
  351. if (i == )
  352. printf("");
  353. scanf("%s", str);
  354. if (str[] == 'A'){
  355. int l, r, x;
  356. scanf("%d%d%d", &l, &r, &x);
  357. if (r>= tot) A.add(l, r - l + , x);
  358. }else if (str[] == 'I'){
  359. int l, x;
  360. scanf("%d%d", &l, &x);
  361. data[] = x;
  362. A.Insert(l, , data);
  363. tot++;
  364. }else if (str[] == 'M'){
  365. int l, r;
  366. scanf("%d%d", &l, &r);
  367. if (r >= tot) printf("%d\n", A.getMin(l, r - l + ));
  368. }else if (str[] == 'D'){
  369. int l;
  370. scanf("%d", &l);
  371. tot--;
  372. if (l >= tot) A.Delete(l, );
  373. }else if (!strcmp(str, "REVERSE")){
  374. int l, r;
  375. scanf("%d%d", &l, &r);
  376. if (l == r) continue;
  377. if (r >= tot )A.Reverse(l, r - l + );
  378. }else{
  379. int l, r, t;
  380. scanf("%d%d%d", &l, &r, &t);
  381. //注意t可能为-
  382. int len = r - l + ;
  383. t = (t%len + len) % len;
  384. if (t && r >= tot) A.Revolve(l, r - t, r);
  385. }
  386. }
  387. }
  388. void debug(){
  389. data[] = ;
  390. data[] = ;
  391. data[] = ;
  392. A.Insert(, , data);data[] = ; data[] = ;
  393. A.Insert(, , data);data[] = ; data[] = ;
  394. A.Insert(, , data);
  395. //A.Reverse(2, 4);
  396. //A.split(A.head, 1);
  397. A.print();
  398. printf("\n%d", A.getMin(, ));
  399. }
  400.  
  401. int main(){
  402. #ifdef LOCAL
  403. freopen("data.txt", "r", stdin);
  404. freopen("std.txt", "w", stdout);
  405. #endif
  406. init();
  407. work();
  408. //debug();
  409. return ;
  410. }

【POJ3580】【块状链表】SuperMemo的更多相关文章

  1. 【BZOJ-1507】Editor 块状链表

    1507: [NOI2003]Editor Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 3397  Solved: 1360[Submit][Stat ...

  2. ZOJ 2112 Dynamic Rankings(动态区间第 k 大+块状链表)

    题目大意 给定一个数列,编号从 1 到 n,现在有 m 个操作,操作分两类: 1. 修改数列中某个位置的数的值为 val 2. 询问 [L, R] 这个区间中第 k 大的是多少 n<=50,00 ...

  3. POJ 2887 Big String(块状链表)

    题目大意 给一个字符串,长度不超过 106,有两种操作: 1. 在第 i 个字符的前面添加一个字符 ch 2. 查询第 k 个位置是什么字符 操作的总数不超过 2000 做法分析 好多不同的做法都可以 ...

  4. 【BZOJ 1507】【NOI 2003】&【Tyvj P2388】Editor 块状链表模板题

    2016-06-18 当时关于块状链表的想法是错误的,之前维护的是一个动态的$\sqrt{n}$,所以常数巨大,今天才知道原因TwT,请不要参照这个程序为模板!!! 模板题水啊水~~~ 第一次写块状链 ...

  5. BZOJ 1507 Editor(块状链表)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1507 题意:一个文本编辑器,模拟以下操作: 思路:块状链表的主要操作: (1)find( ...

  6. bzoj 3809 Gty的二逼妹子序列(莫队算法,块状链表)

    [题意] 回答若干个询问,(l,r,a,b):区间[l,r]内权值在[a,b]的数有多少[种]. [思路] 考虑使用块状链表实现莫队算法中的插入与删除. 因为权值处于1..n之间,所以我们可以建一个基 ...

  7. 【BZOJ1500】【块状链表】维修数列

    Description Input 输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述 ...

  8. 【BZOJ2741】【块状链表+可持久化trie】FOTILE模拟赛L

    Description FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 .. ...

  9. 【BZOJ3295】【块状链表+树状数组】动态逆序对

    Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计 ...

  10. 【HDU4391】【块状链表】Paint The Wall

    Problem Description As a amateur artist, Xenocide loves painting the wall. The wall can be considere ...

随机推荐

  1. HDU-4405 Aeroplane chess

    http://acm.hdu.edu.cn/showproblem.php?pid=4405 看了一下这个博客http://kicd.blog.163.com/blog/static/12696191 ...

  2. extjs+Aspose.Cells导出到Excel

    1.&=DataSource.Field,&=[DataSource].[Field]是对DataTable和几何类型的引用,将会从当前行开始竖直向下生成多行数据. 2.&=$ ...

  3. Python根据上下限生成不重复随机数1

    Python 2.7.5代码: #coding=utf-8 import random #定义计数器,默认为0 num=0 #定义随机结果集,默认为空列表 choose_resault=[] #最多可 ...

  4. unity3d 雪与沙的渲染

    很简单的一个shader,跟着上一篇地形顺便弄的 方法就是基于物理的diffuse,再加上noise权重的specular 公式参考 JOURNEY JOURNEY中认为OrenNayar比较浪费,所 ...

  5. poj 2975 Nim(博弈)

    Nim Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5232   Accepted: 2444 Description N ...

  6. HDU 2089 不要62(挖个坑=-=)

    不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  7. 图形变幻矩阵 Transforms

    https://developer.apple.com/library/mac/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d ...

  8. 字符集(CHARACTER SET)和校对集(COLLATE)

    http://blog.sina.com.cn/s/blog_9707fac301016wxm.html http://www.th7.cn/db/mysql/201412/84636.shtml 从 ...

  9. Gwt 整合FusionCharts及封装搜狗地图时出现的问题

    smartGwt 整合FusionCharts 把需要的.swf文件和FusionCharts.js放在war下面(路径就自己定了) 可以工程的html文件中引FusionCharts.js文件 也可 ...

  10. cmake 手册系列

    http://www.cnblogs.com/coderfenghc/archive/2012/06/16/CMake_ch_01.html