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, {A1, A2, ... An}. Then the host performs a series of operations and queries on the sequence which consists:
- 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}
- 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}
- REVOLVE x y T: rotate sub-sequence {Ax ... Ay} T times. For example, performing "REVOLVE 2 4 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 2, 5}
- 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}
- DELETE x: delete Ax. For example, performing "DELETE 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5}
- 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 n (n ≤ 100000).
The following n lines describe the sequence.
Then follows M (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
Solution
能整合的操作大部分都整合了...所以这是个毒瘤题(码农题),不过维修序列貌似比这题更恐怖。
这题要求资瓷区间加,区间反转,区间旋转(其实就是从中间断开然后左右交换位置),单点插入,单点删除,区间查询最小值。
这些都能用fhqtreap解决。
区间加(和线段树),区间反转(^=1,交换左右子树)都打标记就行了,分裂合并的时候下传标记。其实就是码码码,没有别的...
然后注意一个坑就是poj的g++不资瓷time函数,我因为这个查了1h一直以为哪里写挂了,然后换成某八位质数就过了...(换成c++提交也没事...)
#include <cstdio>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <queue>
using namespace std;
#define N 500010
#define lc (t[rt].l)
#define rc (t[rt].r)
inline void in(int &x) {
x = 0; int f = 1; char c = getchar();
while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
x *= f;
}
const int inf = 1e9+1;
int n, m, root, tot;
struct fhq { int flag, l, r, siz, rnd, val, mn, tag; } t[N];
void rev(int rt) { t[rt].flag ^= 1; swap(lc, rc); }
void addone(int rt, int c) {
if(!rt) return;
t[rt].val += c; t[rt].mn += c; t[rt].tag += c;
}
void up(int rt) {
if(!rt) return;
t[rt].mn = min(t[rt].val, min(t[lc].mn, t[rc].mn));
t[rt].siz = 1 + t[lc].siz + t[rc].siz;
}
void down(int rt) {
if(!rt) return;
if(t[rt].tag) addone(lc, t[rt].tag), addone(rc, t[rt].tag);
if(t[rt].flag) rev(lc), rev(rc);
t[rt].tag = t[rt].flag = 0;
}
void split(int rt, int &l, int &r, int k) {
if(!k) l = 0, r = rt;
else if(k == t[rt].siz) l = rt, r = 0;
else if(k <= t[lc].siz) down(r=rt), split(lc, l, lc, k), up(rt);
else down(l=rt), split(rc, rc, r, k - t[lc].siz - 1), up(rt);
}
void merge(int &rt, int l, int r) {
if(!l || !r) rt = l + r;
else if(t[l].rnd < t[r].rnd) down(rt=l), merge(rc, rc, r), up(rt);
else down(rt=r), merge(lc, l, lc), up(rt);
}
int build(int x) {
t[++tot].rnd = rand()<<15|rand();
t[tot].siz = 1;
t[tot].val = t[tot].mn = x;
return tot;
}
void add(int l, int r, int c) {
int x, y, tmp;
split(root, x, y, r); split(x, x, tmp, l - 1);
addone(tmp, c);
merge(x, x, tmp); merge(root, x, y);
}
void reverse(int l, int r) {
int x, y, tmp;
split(root, x, y, r); split(x, x, tmp, l - 1);
rev(tmp);
merge(x, x, tmp); merge(root, x, y);
}
void del(int k) {
int x, y, tmp;
split(root, x, y, k); split(x, x, tmp, k - 1);
merge(root, x, y);
}
void insert(int k, int v) {
int x, y;
split(root, x, y, k); int tmp = build(v);
merge(x, x, tmp); merge(root, x, y);
}
void revolve(int l, int r, int v) {
int x, y, tmp, z;
split(root, x, y, r-v); split(y, z, y, v);
split(x, x, tmp, l-1);
merge(tmp, z, tmp); merge(x, x, tmp); merge(root, x, y);
}
int query(int l, int r) {
int x, y, tmp;
split(root, x, y, r); split(x, x, tmp, l - 1);
int ans = t[tmp].mn;
merge(x, x, tmp); merge(root, x, y);
return ans;
}
int main() {
srand((unsigned)time(0)); in(n);
t[0].mn = t[0].val = t[0].rnd = inf;
for(int i = 1, x; i <= n; ++i) {
in(x);
merge(root, root, build(x));
}
in(m);
for(int i = 1; i <= m; ++i) {
int l, r, v; char ch[20];
scanf("%s", ch);
if(ch[0] == 'A') in(l), in(r), in(v), add(l, r, v);
else if(ch[0] == 'R' && ch[3] == 'E') in(l), in(r), reverse(l, r);
else if(ch[0] == 'R' && ch[3] == 'O') in(l), in(r), in(v), revolve(l, r, v%(r-l+1));
else if(ch[0] == 'I') in(l), in(v), insert(l, v);
else if(ch[0] == 'D') in(l), del(l);
else in(l), in(r), printf("%d\n", query(l, r));
}
return 0;
}