Poj3580 Super Memo(FHQ-Treap)
阿新 • • 發佈:2018-12-22
題面
題解
對於操作$1$,我們可以對於每個節點打一個$add$標記,下放就行了
對於操作2,可以參考這篇題解的上一篇,不贅述
對於操作4,可以將區間裂成兩部分,然後再插入合併
對於操作5,可以將區間裂成三部分,刪除其中一個部分,合併其他兩部分
對於操作6,打一個$min$標記,具體可以看程式碼。
對於操作3,這個有點複雜,但是手玩可以發現,修改完後只是某兩個斷開的區間換了位置,只是斷點不確定,算一下即可(細節有點多。)
#include <ctime> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> template<typename T> void read(T &x) { int flag = 1; x = 0; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); } while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag; } const int N = 2e5 + 10; int n, m, lc[N], rc[N], siz[N], val[N], pri[N], rev[N], add[N], mn[N], tot; inline void rotate(int o) { std::swap(lc[o], rc[o]), rev[o] ^= 1; } inline void __add(int o, int v) { val[o] += v, mn[o] += v, add[o] += v; } inline void upt(int o) { siz[o] = siz[lc[o]] + siz[rc[o]] + 1, mn[o] = val[o]; if(lc[o]) mn[o] = std::min(mn[o], mn[lc[o]]); if(rc[o]) mn[o] = std::min(mn[o], mn[rc[o]]); } inline int node(int x) { val[++tot] = x, pri[tot] = rand(), siz[tot] = 1, mn[tot] = x; return tot; } void pushdown(int o) { if(add[o]) { if(lc[o]) __add(lc[o], add[o]); if(rc[o]) __add(rc[o], add[o]); add[o] = 0; } if(rev[o]) { if(lc[o]) rotate(lc[o]); if(rc[o]) rotate(rc[o]); rev[o] = 0; } } void split(int o, int k, int &l, int &r) { if(!o) { l = r = 0; return ; } pushdown(o); if(siz[lc[o]] < k) l = o, split(rc[o], k - siz[lc[o]] - 1, rc[o], r); else r = o, split(lc[o], k, l, lc[o]); upt(o); } int merge(int l, int r) { if(!l || !r) return l + r; pushdown(l), pushdown(r); if(pri[l] < pri[r]) { rc[l] = merge(rc[l], r), upt(l); return l; } else { lc[r] = merge(l, lc[r]), upt(r); return r; } } int main () { read(n), srand(19260817); int x, y, l, r, k, rt = 0, D, T; for(int i = 1; i <= n; ++i) read(x), rt = merge(rt, node(x)); read(m); char opt[10]; for(int i = 1; i <= m; ++i) { scanf("%s", opt), read(x); if(opt[0] == 'A') { read(y), read(D); split(rt, y, l, r), split(l, x - 1, l, k); __add(k, D), rt = merge(merge(l, k), r); } if(opt[0] == 'R' && opt[3] == 'E') { read(y), split(rt, y, l, r), split(l, x - 1, l, k); rotate(k), rt = merge(merge(l, k), r); } if(opt[0] == 'R' && opt[3] == 'O') { read(y), read(T); T %= (y - x + 1); if(!T) continue; T = (y - x + 1) - T; split(rt, y, l, r), split(l, x - 1, l, k); split(k, T, k, D); rt = merge(merge(l, merge(D, k)), r); } if(opt[0] == 'I') read(y), split(rt, x, l, r), rt = merge(merge(l, node(y)), r); if(opt[0] == 'D') split(rt, x, l, r), split(l, x - 1, l, k), rt = merge(l, r); if(opt[0] == 'M') { read(y), split(rt, y, l, r), split(l, x - 1, l, k); printf("%d\n",mn[k]), rt = merge(merge(l, k), r); } } return 0; }