能整合的操作大部分都整合了...所以这是个毒瘤题(码农题),不过维修序列貌似比这题更恐怖。
这题要求资瓷区间加,区间反转,区间旋转(其实就是从中间断开然后左右交换位置),单点插入,单点删除,区间查询最小值。
这些都能用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; }