HDU 3726 Graph and Queries
http://acm.hdu.edu.cn/showproblem.php?pid=3726
离线逆序操作启发式合并找第K大值
#include <iostream> #include <cstdio> #include <vector> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <climits> using namespace std; #define N 50005 struct Treap { int root[N] , priority[N] , child[N][2]; int key[N]; int Size[N] , cnt[N]; vector<int> del; Treap() { priority[0] = 0x7FFFFFFF; } void clear() { del.clear(); } int size(int x) { return Size[root[x]]; } void update(int x) { Size[x] = Size[child[x][0]] + Size[child[x][1]] + cnt[x]; } void rotate (int& x , int t) { int y = child[x][t]; child[x][t] = child[y][t ^ 1]; child[y][t ^ 1] = x; update(x) , update(y); x = y; } void __insert(int& x , int k) { if (x) { if (key[x] == k) ++ cnt[x]; else { int t = key[x] < k; __insert(child[x][t] , k); if (priority[child[x][t]] < priority[x]) rotate(x , t); } } else { x = del.back(); del.pop_back(); key[x] = k; cnt[x] = 1; priority[x] = rand() << 15 | rand(); child[x][0] = child[x][1] = 0; } update(x); } void __erase(int& x , int k) { //if (!x) return; if (key[x] == k) { if (cnt[x] > 1) -- cnt[x]; else { if (!child[x][0] && !child[x][1]) { del.push_back(x); cnt[x] = 0 , x = 0; return; } int t = priority[child[x][0]] > priority[child[x][1]]; rotate(x , t); __erase(x , k); } } else __erase(child[x][key[x] < k] , k); update(x); } int __getKth(int& x , int k) { if (k <= Size[child[x][0]]) return __getKth(child[x][0] , k); k -= Size[child[x][0]] + cnt[x]; if (k <= 0) return key[x]; return __getKth(child[x][1] , k); } void merge(int& x , int& y) { if (child[x][0]) merge(child[x][0] , y); if (child[x][1]) merge(child[x][1] , y); int z = key[x]; while(cnt[x] > 1) { __erase(x , z); if (z != -1 << 30) __insert(y , z); } __erase(x , z); if (z != -1 << 30) __insert(y , z); } }; #define Nnum 20005 #define Mnum 60005 #define Qnum 500005 int n , m , Q , ca; Treap T; struct edge { int x , y; bool f; }e[Mnum]; struct query { int id , x , y; }q[Qnum]; int f[Nnum] , a[Nnum]; int getf(int x) {return x == f[x] ? x : f[x] = getf(f[x]);} void work() { int i , j , x , y , z; char str[3]; for (i = 1 ; i <= n ; ++ i) scanf("%d",&a[i]) , f[i] = i; for (i = 1 ; i <= m ; ++ i) scanf("%d%d",&e[i].x, &e[i].y) , e[i].f = 0; Q = 0 , T.clear(); for (i = n + n/2; i > 0 ; -- i) T.del.push_back(n + i); while (scanf("%s" , str) , str[0] != 'E') { if (str[0] == 'D') q[++ Q].id = 0; if (str[0] == 'Q') q[++ Q].id = 1; if (str[0] == 'C') q[++ Q].id = 2; scanf("%d",&q[Q].x); if (q[Q].id) scanf("%d",&q[Q].y); if (q[Q].id == 0) { e[q[Q].x].f = 1; } if (q[Q].id == 2) { q[Q].y -= a[q[Q].x]; a[q[Q].x] += q[Q].y; } } for (i = 1 ; i <= m ; ++ i) if (!e[i].f) f[getf(e[i].x)] = getf(e[i].y); for (i = 1 ; i <= n ; ++ i) { T.root[i] = i; T.cnt[i] = 0 , T.priority[i] = INT_MIN , T.key[i] = -1 << 30; T.child[i][0] = T.child[i][1] = 0; x = i; T.__insert(T.root[i] , a[i]); } for (i = 1 ; i <= n ; ++ i) if (getf(i) != i) { T.__erase(T.root[i] , a[i]) ; T.__insert(T.root[getf(i)] , a[i]); } long long ans = 0 , tot = 0; for (i = Q ; i > 0 ; -- i) { if (q[i].id == 0) { j = q[i].x; x = getf(e[j].x) , y = getf(e[j].y); if (x == y) continue; if (T.size(x) > T.size(y)) swap(x , y); f[x] = y; T.merge(T.root[x] , T.root[y]); } if (q[i].id == 1) { x = getf(q[i].x) , ++ tot; j = T.size(x); if (q[i].y < 1 || q[i].y > j) continue; ans += T.__getKth(T.root[x] , j - q[i].y + 1); } if (q[i].id == 2) { x = getf(q[i].x); T.__erase(T.root[x] , a[q[i].x]); a[q[i].x] -= q[i].y; T.__insert(T.root[x] , a[q[i].x]); } } printf("Case %d: %lf\n" , ++ ca , tot ? 1.0 * ans / tot : 0.0); } int main() { //srand((unsigned int)time(0)); while (scanf("%d%d",&n,&m) , n || m) //int _; cin >> _;while (_--) work(); return 0; }
SCU4285
http://cstest.scu.edu.cn/soj/problem.action?id=4285
可以拿set简单过的,用Treap写了写体会了一下如何进行垃圾回收
#include <iostream> #include <cstdio> #include <vector> #include <cmath> #include <cstring> #include <algorithm> #include <set> using namespace std; #define N 10005 struct Treap { int root , nodecnt , priority[N] , child[N][2]; int key[N]; int Size[N] , cnt[N]; vector<int> del; Treap(){ del.clear(); root = 0 , nodecnt = 1; priority[0] = key[0] = 1 << 30; Size[0] = 0; } void clear() { del.clear(); root = 0 , nodecnt = 1; priority[0] = -1 << 30 , key[0] = -1<<30; Size[0] = 0; } int size() { return Size[root]; } void update(int x) { Size[x] = Size[child[x][0]] + Size[child[x][1]] + cnt[x]; } void rotate (int& x , int t) { int y = child[x][t]; child[x][t] = child[y][t ^ 1]; child[y][t ^ 1] = x; update(x) , update(y); x = y; } void __insert(int& x , int k) { if (x) { if (key[x] == k) x = x;//++ cnt[x]; else { int t = key[x] < k; __insert(child[x][t] , k); if (priority[child[x][t]] > priority[x]) rotate(x , t); } } else { if (del.size()) { x = del.back(); del.pop_back(); } else x = nodecnt ++; key[x] = k; cnt[x] = 1; priority[x] = rand(); child[x][0] = child[x][1] = 0; } update(x); } void __erase(int& x , int k) { if (!x) return; if (key[x] == k) { // if (cnt[x] > 1) // -- cnt[x]; // else { if (!child[x][0] && !child[x][1]) { del.push_back(x); x = 0; return; } int t = priority[child[x][0]] < priority[child[x][1]]; rotate(x , t); __erase(x , k); } } else __erase(child[x][key[x] < k] , k); update(x); } int __getKth(int& x , int k) { if (k <= Size[child[x][0]]) return __getKth(child[x][0] , k); k -= Size[child[x][0]] + cnt[x]; if (k <= 0) return key[x]; return __getKth(child[x][1] , k); } void insert(int x){ __insert(root , x);} void erase(int x){ __erase(root , x);} int getKth(int x){ return __getKth(root , x);} }; int n , m ; Treap mx , mn; void work() { int i , x , y; scanf("%d",&n); mx.clear() , mn.clear(); while (n --) { scanf("%d",&m); while (m --) { scanf("%d",&x); mx.insert(x); if (mx.size() > n + 3) mx.erase(mx.getKth(1)); mn.insert(x) ; if (mn.size() > n + 3) mn.erase(mn.getKth(mn.size())); } if (mx.size() < 2 || mn.size() < 2) puts("-1 -1"); else { x = mn.getKth(2); y = mx.getKth(mx.size() - 1); printf("%d %d\n" , x , y); mx.erase(x) , mn.erase(x); mx.erase(y) , mn.erase(y); } } } int main() { int _; cin >> _;while (_--) work(); return 0; }
区间互不包含这个条件非常强呀……区间排序之后从左往右扫一遍出解
int n , m , ans[N] , a[N]; struct query { int l , r , k , num; bool operator < (const query& p) const{ if(l == p.l) return r < p.r; return l < p.l;} }q[N]; Treap T; void work() { int i , x , y , j; scanf("%d%d",&n,&m); for (i = 1 ; i <= n ; ++ i) scanf("%d",&a[i]); for (i = 0 ; i < m ; ++ i) scanf("%d%d%d",&q[i].l , &q[i].r , &q[i].k) , q[i].num = i; sort(q , q + m); x = 0 , y = 1; for (i = 0 ; i < m ; ++ i) { while (q[i].r > x) T.insert(a[++ x]); while (q[i].l > y) T.erase(a[y ++]); ans[q[i].num] = T.getKth(q[i].k); } for (i = 0 ; i < m ; ++ i) printf("%d\n" , ans[i]); }
http://poj.org/problem?id=2750
线段树,维护区间的权值和最大和最小的段
#include <iostream> #include <cstdio> #include <vector> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <climits> using namespace std; #define N 100005 #define M 1000005 int n , m , a[N]; struct stree { int sum; int lmax , rmax , smax; int lmin , rmin , smin; }t[N << 1]; int id(int l , int r) {return l + r | l != r;} #define MID int mid = (l + r) >> 1; #define ID id(l , r) #define Left l , mid #define Right mid + 1 , r void pushup(int l , int r) { MID; int p = ID , LL = id(Left) , RR = id(Right); t[p].sum = t[LL].sum + t[RR].sum; t[p].lmax = max(t[LL].sum + t[RR].lmax , t[LL].lmax); t[p].rmax = max(t[RR].sum + t[LL].rmax , t[RR].rmax); t[p].smax = max(t[LL].rmax + t[RR].lmax , max(t[LL].smax , t[RR].smax)); t[p].lmin = min(t[LL].sum + t[RR].lmin , t[LL].lmin); t[p].rmin = min(t[RR].sum + t[LL].rmin , t[RR].rmin); t[p].smin = min(t[LL].rmin + t[RR].lmin , min(t[LL].smin , t[RR].smin)); } void update(int l , int r , int i , int x) { if (l == r) { int p = ID; t[p].sum = x; t[p].lmax = t[p].rmax = t[p].smax = x; t[p].lmin = t[p].rmin = t[p].smin = x; return;} if (l == r) return; MID; if (i <= mid) update(Left , i , x); if (i > mid) update(Right , i , x); pushup(l , r); } void Build(int l , int r) { if (l == r) { int p = ID; t[p].sum = a[l]; t[p].lmax = t[p].rmax = t[p].smax = a[l]; t[p].lmin = t[p].rmin = t[p].smin = a[l]; return;} MID;Build(Left);Build(Right);pushup(l , r); } void work() { int i , x , y , p , ans = 0; scanf("%d",&n); for (i = 1 ; i <= n ; ++ i) scanf("%d",&a[i]); Build(1 , n) , p = id(1 , n); scanf("%d",&m); while (m --) { scanf("%d%d",&x,&y); update(1 , n , x , y); ans = t[p].sum - t[p].smin; if (t[p].sum != t[p].smax) ans = max(t[p].smax , ans); printf("%d\n" , ans); } } int main() { work(); return 0; }
BZOJ1503 [NOI2004]郁闷的出纳员
http://www.lydsy.com/JudgeOnline/problem.php?id=1503
简单的Treap操作
int n , Q; Treap T; void work() { int i , x , y , ans = 0 , add = 0; char str[5]; scanf("%d%d",&n,&Q); T.clear(); while (n --) { scanf("%s" , str); if (*str == 'I') { scanf("%d",&x); if (x < Q); // ++ ans; else T.insert(x - add); } if (*str == 'S') { scanf("%d",&x); add -= x; while (T.size() && (y = T.getKth(1)) + add - Q < 0) T.erase(y) , ++ ans; } if (*str == 'A') { scanf("%d",&x); add += x; } if (*str == 'F') { scanf("%d",&x); if (x > T.size()) puts("-1"); else printf("%d\n" , T.getKth(T.size() - x + 1) + add); } } printf("%d" , ans); }
http://www.lydsy.com/JudgeOnline/problem.php?id=1208
multiset也能过
int n; Treap pet[2]; void work() { int i , x , k , l , r , ans = 0; pet[0].clear() , pet[1].clear(); scanf("%d",&n); while (n --) { scanf("%d%d",&i,&x); if (!pet[i].size()) pet[i ^ 1].insert(x); else { k = pet[i].Rank(x); if (k == 0) { r = pet[i].getKth(1); ans += abs(r - x) , ans %= 1000000; pet[i].erase(r); continue; } if (k == pet[i].size()) { l = pet[i].getKth(pet[i].size()); ans += abs(l - x) , ans %= 1000000; pet[i].erase(l); continue; } l = pet[i].getKth(k); if (l == x) continue; r = pet[i].getKth(k + 1); if (abs(l - x) <= abs(r - x)) ans += abs(l - x) , ans %= 1000000 , pet[i].erase(l); else ans += abs(r - x) , ans %= 1000000 , pet[i].erase(r); } } printf("%d\n" , ans); }
http://www.lydsy.com/JudgeOnline/problem.php?id=1798
线段树,注意标记下传的顺序
#include <iostream> #include <cstdio> #include <vector> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <climits> using namespace std; #define N 100005 #define M 1000005 int n , m , a[N] , Q; struct stree { long long sum , multi , add; }t[N << 1]; int id(int l , int r) {return l + r | l != r;} #define MID int mid = (l + r) >> 1; #define ID id(l , r) #define Left l , mid #define Right mid + 1 , r void Multi(int Id , int x) { t[Id].multi = t[Id].multi * x % Q; t[Id].sum = t[Id].sum * x % Q; t[Id].add = t[Id].add * x % Q; } void pushup(int l , int r) { MID; int p = ID , LL = id(Left) , RR = id(Right); t[p].sum = (t[LL].sum + t[RR].sum) % Q; } void pushdown(int l , int r) { MID; int p = ID , LL = id(Left) , RR = id(Right); if (t[p].multi != 1 % Q) { Multi(LL , t[p].multi); Multi(RR , t[p].multi); t[p].multi = 1 % Q; } if (t[p].add) { t[LL].sum = (t[LL].sum + t[p].add * (mid - l + 1)) % Q; t[LL].add = (t[LL].add + t[p].add) % Q; t[RR].sum = (t[RR].sum + t[p].add * (r - mid)) % Q; t[RR].add = (t[RR].add + t[p].add) % Q; t[p].add = 0; } } void update(int l , int r , int top , int bot , int q , int w) { if (top <= l && r <= bot) {int p = ID; if (q == 1) Multi(ID , w); if (q == 2) t[p].add = (t[p].add + w) % Q , t[p].sum = (t[p].sum + w * (r - l + 1)) % Q; return;}MID;pushdown(l , r); if (top <= mid) update(Left , top , bot , q , w); if (bot > mid) update(Right , top , bot , q , w); pushup(l , r); } int Query(int l , int r , int top , int bot) { if (top <= l && r <= bot) {return t[ID].sum;}MID;pushdown(l , r);int ans = 0; if (top <= mid) ans += Query(Left , top , bot); if (bot > mid) ans += Query(Right , top , bot); pushup(l , r); return ans % Q; } void Build(int l , int r) { t[ID].multi = 1; if (l == r) {t[ID].sum = a[l];return;} MID;Build(Left);Build(Right);pushup(l , r); } void work() { int i , x , y , c , ans = 0; scanf("%d%d",&n,&Q); for (i = 1 ; i <= n ; ++ i) scanf("%d",&a[i]); Build(1 , n); scanf("%d",&m); while (m --) { scanf("%d%d%d",&i,&x,&y); if (i < 3) scanf("%d" ,&c) , update(1 , n , x , y , i , c); else printf("%d\n" , Query(1 , n , x , y)); } } int main() { work(); return 0; }
ZJU2112 Dynamic Rankings
树套树,后来用树状数组套主席树写过但是MLE了,树状数组套主席树的空间消耗的确很大,相应却有优秀的时间效率
#include <iostream> #include <cstdio> #include <vector> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <climits> using namespace std; #define N 50005 #define M 1000005 struct Treap { int root , nodecnt , priority[M] , child[M][2]; int key[M]; int Size[M] , cnt[M]; vector<int> del; void clear() { root = 0 , nodecnt = 1; priority[0] = INT_MIN; child[0][0] = child[0][1] = 0; key[0] = INT_MIN , cnt[0] = 0 , Size[0] = 0; del.clear(); } void update(int x) { Size[x] = Size[child[x][0]] + Size[child[x][1]] + cnt[x]; } void rotate (int& x , int t) { int y = child[x][t]; child[x][t] = child[y][t ^ 1]; child[y][t ^ 1] = x; update(x) , update(y); x = y; } void __insert(int& x , int k) { if (x) { if (key[x] == k) ++ cnt[x]; else { int t = key[x] < k; __insert(child[x][t] , k); if (priority[child[x][t]] > priority[x]) rotate(x , t); } } else { if (del.size()) { x = del.back(); del.pop_back(); } else x = nodecnt ++; key[x] = k; cnt[x] = 1; priority[x] = rand() << 15 | rand(); child[x][0] = child[x][1] = 0; } update(x); } void __erase(int& x , int k) { //if (!x) return; if (key[x] == k) { if (cnt[x] > 1) -- cnt[x]; else { if (!child[x][0] && !child[x][1]) { del.push_back(x); cnt[x] = 0 , x = 0; return; } int t = priority[child[x][0]] < priority[child[x][1]]; rotate(x , t); __erase(x , k); } } else __erase(child[x][key[x] < k] , k); update(x); } int __Rank(int& x , int k) { if(!x) return 0; if (k < key[x]) return __Rank(child[x][0] , k); int Rk = Size[child[x][0]] + cnt[x]; if (k > key[x]) Rk += __Rank(child[x][1] , k); return Rk; } int __getKth(int& x , int k) { if (k <= Size[child[x][0]]) return __getKth(child[x][0] , k); k -= Size[child[x][0]] + cnt[x]; if (k <= 0) return key[x]; return __getKth(child[x][1] , k); } /*void insert(int x){ __insert(root , x);} void erase(int x){ __erase(root , x);} int getKth(int x){ return __getKth(root , x);}*/ }; int n , m , a[N] , ans; Treap T; int t[N << 1]; int id(int l , int r) {return l + r | l != r;} #define MID int mid = (l + r) >> 1; #define ID id(l , r) #define Left l , mid #define Right mid + 1 , r void SInsert(int l , int r , int i , int x) { T.__insert(t[ID] , x); if (l == r) return; MID; if (i <= mid) SInsert(Left , i , x); if (i > mid) SInsert(Right , i , x); } void SErase(int l , int r , int i , int x) { T.__erase(t[ID] , x); if (l == r) return; MID; if (i <= mid) SErase(Left , i , x); if (i > mid) SErase(Right , i , x); } void SQuery(int l , int r , int top , int bot , int x) { if (top <= l && r <= bot) {ans += T.__Rank(t[ID] , x); return;} MID; if (top <= mid) SQuery(Left , top , bot , x); if (bot > mid) SQuery(Right , top , bot , x); } void work() { int i , x , y , l , r , mid , p; char s[5]; memset(t , 0 , sizeof(t)) , T.clear(); memset(a , 0 , sizeof(a)); scanf("%d%d" ,&n,&m); for (i = 1 ; i <= n ; ++ i) scanf("%d",&a[i]) , SInsert(1 , n , i , a[i]); while (m --) { scanf("%s" , s); if (*s == 'C') { scanf("%d%d",&x,&y); SErase(1 , n , x , a[x]); a[x] = y; SInsert(1 , n , x , a[x]); } else { scanf("%d%d%d",&x,&y,&p); l = 0 , r = 1 << 30; while (l < r) { mid = (l + r) >> 1 , ans = 0; SQuery(1 , n , x , y , mid); if(ans < p) l = mid + 1; else r = mid; } printf("%d\n" , l); } } } int main() { freopen("~input.txt","r",stdin); //srand((unsigned int)time(0)); //while (scanf("%d%d",&n,&m) , n || m) int _; cin >> _;while (_--) work(); return 0; }
线段树维护树的DFS序列,这样边权的变换和询问都可以转换到一个区间上的问题。
都有DFS序列了所以求LCA可以转成RMQ,但是还是偷懒直接倍增LCA了
#include <iostream> #include <cstdio> #include <vector> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <stack> using namespace std; #define N 100005 #define M 1000005 int n , mcnt , pre[N] , f[N][17] , m , dis[N] , dep[N]; int cnt , begin[N] , end[N] , a[N] , ans; struct edge { int x , w , next; }e[N << 1]; struct stree { int w , f; } t[N << 1]; int id(int l , int r) {return l + r | l != r;} #define MID int mid = (l + r) >> 1; #define ID id(l , r) #define Left l , mid #define Right mid + 1 , r void pushup(int l , int r) { MID;t[ID].w = max(t[id(Left)].w , t[id(Right)].w); } void pushdown(int l , int r) { MID ;int p = ID , LL = id(Left) , RR = id(Right); if (t[p].f) { t[LL].w += t[p].f , t[LL].f += t[p].f ; t[RR].f += t[p].f , t[RR].w += t[p].f ; t[p].f = 0; } } void Build(int l , int r) { if (l == r) {t[ID].w = a[l]; t[ID].f = 0 ;return;} MID;Build(Left);Build(Right);pushup(l , r); } void Query(int l , int r , int top , int bot) { if (top <= l && r <= bot) {ans = max(ans , t[ID].w); return;} MID; pushdown(l , r); if (top <= mid) Query(Left , top , bot); if (bot > mid) Query(Right , top , bot); pushup(l , r); } void Update(int l , int r , int top , int bot , int x) { if (top <= l && r <= bot) {t[ID].f += x , t[ID].w += x; return;} MID; pushdown(l , r); if (top <= mid) Update(Left , top , bot , x); if (bot > mid) Update(Right , top , bot , x); pushup(l , r); } void dfs(int x , int fa , int d , int w , int p) { f[x][0] = fa , dis[x] = w , a[++ cnt] = d , begin[x] = cnt , dep[x] = p; for (int i = pre[x] ; ~i ; i = e[i].next) if (e[i].x != fa) dfs(e[i].x , x , d + e[i].w , e[i].w , p + 1); end[x] = cnt; } int LCA(int x , int y) { int log , i ; if (dep[x] < dep[y]) swap(x , y); // x is deeper than y for (log = 1 ; (1 << log) <= dep[x] ; ++ log); -- log; for (i = log ; i >= 0 ; -- i) if (dep[x] - (1 << i) >= dep[y]) x = f[x][i]; if (x == y) return y; // y is ancstor of x for (i = log ; i >= 0 ; -- i) if (f[x][i] && f[x][i] != f[y][i]) x = f[x][i] , y = f[y][i]; return f[x][0]; } void work() { int i , j , x , y , z; scanf("%d",&n); memset(pre , -1 , sizeof(pre)) , mcnt = 0; memset(t , 0 , sizeof(t)); memset(a , 0 , sizeof(a)); memset(f , 0 , sizeof(f)); for (i = 1 ; i < n ; ++ i) { scanf("%d%d%d",&x,&y,&z); e[mcnt] = (edge) {y , z , pre[x]} , pre[x] = mcnt ++; e[mcnt] = (edge) {x , z , pre[y]} , pre[y] = mcnt ++; } cnt = 0; dfs(1 , 0 , 0 , 0 , 0); for (j = 1 ; 1 << j < n ; ++ j) for (i = 1 ; i <= n ; ++ i) f[i][j] = f[f[i][j - 1]][j - 1]; Build(1 , n); scanf("%d",&m); int pos = 1; while (m --) { scanf("%d",&i); if (i == 1) { scanf("%d",&x); y = LCA(x , pos); ans = -1 << 30; j = 0; Query(1 , n , begin[x] , begin[x]) , j += ans; ans = -1 << 30; Query(1 , n , begin[pos] , begin[pos]) , j += ans; ans = -1 << 30; Query(1 , n , begin[y] , begin[y]) , j -= ans << 1; printf("%d\n" , j); pos = x; } if (i == 2) { ans = -1 << 30; Query(1 , n , begin[pos] , begin[pos]); j = ans; ans = -1 << 30; Query(1 , n , begin[pos] , end[pos]); printf("%d\n" , ans - j); } if (i == 3) { scanf("%d%d%d",&x,&y,&z); if (dep[x] < dep[y]) swap(x , y); Update(1 , n , begin[x] , end[x] , z - dis[x]); dis[x] = z; } } } int main() { int _; cin >> _;while (_--) work(); return 0; }HDU2665 Kth number
http://acm.hdu.edu.cn/showproblem.php?pid=2665
看了主席树资料的以后YY写了一个,就拿这道题开刀了维护的是一个离散化之后的权值“前缀和”的东西,其实就是可以理解为开了n棵线段树,但是只占了O(nlogn)的空间。
如果是带单点修改的话就需要用树状数组维护这个前缀和了,想起来也非常顺,但是写ZOJ那道题MLE。。
#include <iostream> #include <cstdio> #include <vector> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <climits> using namespace std; #define N 100005 #define M 2000005 int id(int l , int r) {return l + r | l != r;} #define MID int mid = (l + r) >> 1; #define ID id(l , r) #define Left l , mid #define Right mid + 1 , r #define LL child[p][0] #define RR child[p][1] struct Functional_stree { int nodecnt; int root[N]; int child[M][2] , sum[M]; void clear() { nodecnt = 0; root[0] = child[0][0] = child[0][1] = sum[0] = 0; } int newnode() { child[++ nodecnt][0] = child[nodecnt][1] = 0; sum[nodecnt] = 0; return nodecnt; } void insert(int p , int q , int l , int r , int x) { if (l == r) {++ sum[p];return;} MID; if (x <= mid) { LL = newnode() , RR = child[q][1] , sum[LL] = sum[child[q][0]]; insert(LL , child[q][0] , Left , x); } if (x > mid) { RR = newnode() , LL = child[q][0] , sum[RR] = sum[child[q][1]]; insert(RR , child[q][1] , Right , x); } sum[p] = sum[LL] + sum[RR]; } int Query(int p , int q , int l , int r , int k) { if (l == r) return l;MID; if (sum[LL] - sum[child[q][0]] >= k) return Query(LL , child[q][0] , Left , k); return Query(RR , child[q][1] , Right , k - sum[LL] + sum[child[q][0]]); } }; Functional_stree t; int n , a[N] , d[N] , m , Q; void work() { int i , x , y , k; scanf("%d%d",&m,&Q); t.clear(); for (i = 1 ; i <= m ; ++ i) scanf("%d",&a[i]) , d[i] = a[i]; sort(d + 1 , d + m + 1); n = unique(d + 1 , d + m + 1) - d - 1; for (i = 1 ; i <= m ; ++ i) a[i] = lower_bound(d + 1 , d + n + 1 , a[i]) - d; for (i = 1 ; i <= m ; ++ i) { t.root[i] = t.newnode(); t.insert(t.root[i] , t.root[i - 1] , 1 , n , a[i]); } while (Q --) { scanf("%d%d%d",&x,&y,&k); printf("%d\n" , d[t.Query(t.root[y] , t.root[x - 1] , 1 , n , k)]); } } int main() { int _; cin >> _;while (_--) work(); return 0; }
HDU4417 Super Mario
http://acm.hdu.edu.cn/showproblem.php?pid=4417
一段序列求某区间上有多少值<=某个值w
主席树好神好方便啊,就相当于求r这棵树-(l-1)这棵树有多少值<=w..
#include <iostream> #include <cstdio> #include <vector> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <climits> using namespace std; #define N 100005 #define M 2000005 int id(int l , int r) {return l + r | l != r;} #define MID int mid = (l + r) >> 1; #define ID id(l , r) #define Left l , mid #define Right mid + 1 , r #define LL child[p][0] #define RR child[p][1] #define QL child[q][0] #define QR child[q][1] struct Functional_stree { int nodecnt; int root[N]; int child[M][2] , sum[M]; void clear() { nodecnt = 0; root[0] = child[0][0] = child[0][1] = sum[0] = 0; } int newnode() { child[++ nodecnt][0] = child[nodecnt][1] = 0; sum[nodecnt] = 0; return nodecnt; } void insert(int p , int q , int l , int r , int x) { if (l == r) {++ sum[p];return;} MID; if (x <= mid) { LL = newnode() , RR = QR , sum[LL] = sum[QL]; insert(LL , QL , Left , x); } if (x > mid) { RR = newnode() , LL = QL , sum[RR] = sum[QR]; insert(RR , QR , Right , x); } sum[p] = sum[LL] + sum[RR]; } int Query(int p , int q , int l , int r , int k) { if (1 <= l && r <= k) return sum[p] - sum[q];MID; int ans = 0; if (1 <= mid) ans += Query(LL , QL , Left , k); if (k > mid) ans += Query(RR , QR , Right , k); return ans; } }; Functional_stree t; int n , a[N] , d[N] , m , Q , ca; void work() { int i , x , y , k; scanf("%d%d",&m,&Q); t.clear(); for (i = 1 ; i <= m ; ++ i) scanf("%d",&a[i]) , d[i] = a[i]; sort(d + 1 , d + m + 1); n = unique(d + 1 , d + m + 1) - d - 1; for (i = 1 ; i <= m ; ++ i) a[i] = lower_bound(d + 1 , d + n + 1 , a[i]) - d; for (i = 1 ; i <= m ; ++ i) { t.root[i] = t.newnode(); t.insert(t.root[i] , t.root[i - 1] , 1 , n , a[i]); } printf("Case %d:\n" , ++ ca); while (Q --) { scanf("%d%d%d",&x,&y,&k) , ++ x , ++ y; k = upper_bound(d + 1 , d + n + 1 , k) - d - 1; if (!k) puts("0"); else printf("%d\n" , t.Query(t.root[y] , t.root[x - 1] , 1 , n , k)); } } int main() { int _; cin >> _;while (_--) work(); return 0; }
http://acm.hdu.edu.cn/showproblem.php?pid=3804
同样用主席树,和上面那道题差不多
#include <iostream> #include <cstdio> #include <vector> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <queue> using namespace std; #define N 100005 #define M 2000005 int id(int l , int r) {return l + r | l != r;} #define MID int mid = (l + r) >> 1; #define ID id(l , r) #define Left l , mid #define Right mid + 1 , r #define LL child[p][0] #define RR child[p][1] #define QL child[q][0] #define QR child[q][1] struct Functional_stree { int nodecnt; int root[N]; int child[M][2] , sum[M]; void clear() { nodecnt = 0; root[0] = child[0][0] = child[0][1] = sum[0] = 0; } int newnode() { child[++ nodecnt][0] = child[nodecnt][1] = 0; sum[nodecnt] = 0; return nodecnt; } void insert(int p , int q , int l , int r , int x) { if (l == r) {++ sum[p];return;} MID; if (x <= mid) { LL = newnode() , RR = QR , sum[LL] = sum[QL]; insert(LL , QL , Left , x); } if (x > mid) { RR = newnode() , LL = QL , sum[RR] = sum[QR]; insert(RR , QR , Right , x); } sum[p] = sum[LL] + sum[RR]; } int rank(int p , int l , int r , int k) { if (1 <= l && r <= k) return sum[p]; MID; int ans = 0; if (1 <= mid) ans += rank(LL , Left , k); if (k > mid) ans += rank(RR , Right , k); return ans; } int Query(int p , int l , int r , int k) { if (l == r) return l; MID; if (sum[LL] >= k) return Query(LL , Left , k); return Query(RR , Right , k - sum[LL]); } }; Functional_stree t; int n , d[N] , m , Q; struct edge { int x , w , next; }e[N << 1]; int pre[N] , mcnt; bool f[N]; void BFS() { int i , x , y , z; memset(f , 0 , sizeof(f)); queue<int> q; q.push(1) , f[1] = 1; while (!q.empty()) { x = q.front() , q.pop(); for (i = pre[x] ; ~i ; i = e[i].next) if (!f[y = e[i].x]) { z = lower_bound(d + 1 , d + n + 1 , e[i].w) - d; t.root[y] = t.newnode(); t.insert(t.root[y] , t.root[x] , 1 , n , z); f[y] = 1 , q.push(y); } } } void work() { int i , x , y , z , k; scanf("%d",&n) , memset(d , 0 , sizeof(d)) , d[0] = -1; t.clear() , memset(pre , -1 , sizeof(pre)) , mcnt = 0; for (i = 1 ; i < n ; ++ i) { scanf("%d%d%d",&x,&y,&z) , d[i] = z; e[mcnt] = (edge) {y , z , pre[x]} , pre[x] = mcnt ++; e[mcnt] = (edge) {x , z , pre[y]} , pre[y] = mcnt ++; } sort(d + 1 , d + n) , n = unique(d + 1 , d + n) - d - 1; t.root[1] = t.newnode() , BFS(); scanf("%d",&Q); while (Q --) { scanf("%d%d",&x ,&k); if (x == 1) {puts("-1");continue;} k = upper_bound(d + 1 , d + n + 1 , k) - d - 1; if (!k) {puts("-1");continue;}k = t.rank(t.root[x] , 1 , n , k);if (!k) {puts("-1");continue;} printf("%d\n" , d[t.Query(t.root[x] , 1 , n , k)]); } } int main() { int _; cin >> _;while (_--) work(); return 0; }
http://poj.org/problem?id=3580
维护一段序列。。用可以split和merge的Treap写的,昨天至少调了3个小时。。
写完成就感爆棚啊。。
#include <iostream> #include <cstdio> #include <vector> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <climits> using namespace std; #define N 100005 #define M 2000005 struct Segment_Treap { int nodecnt , root; //int root[N]; int key[M] ; int priority[M] , add[M] , sum[M] , mn[M]; int l[M] , r[M]; bool rev[M]; vector<int> del; void clear() { nodecnt = 0 , root = 0; del.clear() , priority[0] = -1 << 30; //root[0] = child[0][0] = child[0][1] = key[0] = 0; } void pushdown(int x) { if (rev[x]) { if(l[x]) swap(l[l[x]] , r[l[x]]) , rev[l[x]] ^= 1; if(r[x]) swap(l[r[x]] , r[r[x]]) , rev[r[x]] ^= 1; rev[x] ^= 1; } if (add[x]) { if(l[x]) mn[l[x]] += add[x] , key[l[x]] += add[x] , add[l[x]] += add[x]; if(r[x]) mn[r[x]] += add[x] , key[r[x]] += add[x] , add[r[x]] += add[x]; add[x] = 0; } } void pushup(int x) { mn[x] = key[x] , sum[x] = 1; if (l[x]) mn[x] = min(mn[x] , mn[l[x]]) , sum[x] += sum[l[x]]; if (r[x]) mn[x] = min(mn[x] , mn[r[x]]) , sum[x] += sum[r[x]]; } void __insert(int& x , int i , int k) { if (x) { pushdown(x); if (sum[l[x]] + 1 >= i) { __insert(l[x] , i , k); int y = l[x]; if (priority[y] < priority[x]) { pushdown(y); l[x] = r[y] , r[y] = x , x = y; pushup(r[x]); } } else { __insert(r[x] , i - sum[l[x]] - 1 , k); int y = r[x]; if (priority[y] < priority[x]) { pushdown(y); r[x] = l[y] , l[y] = x , x = y; pushup(l[x]); } } } else { if (del.size()) x = del.back() , del.pop_back(); else x = ++ nodecnt; mn[x] = key[x] = k , sum[x] = 1; add[x] = rev[x] = 0; priority[x] = rand() << 15 | rand(); l[x] = r[x] = 0; } pushup(x); } void insert(int i , int k) {__insert(root , i , k);} void merge(int& p , int x , int y) { if (!x || !y) p = x | y; else if (priority[x] < priority[y]) pushdown(x) , merge(r[x] , r[x] , y) , pushup(x) , p = x; else pushdown(y) , merge(l[y] , x , l[y]) , pushup(y) , p = y; } void __erase(int& x , int i) { pushdown(x); if (sum[l[x]] + 1 == i) { del.push_back(x); merge(x , l[x] , r[x]); }else if (sum[l[x]] + 1 > i) __erase(l[x] , i) , pushup(x); else if (sum[l[x]] + 1 < i) __erase(r[x] , i - sum[l[x]] - 1) , pushup(x); } void erase(int i) {__erase(root , i);} void split(int p , int& x , int& y , int i) { if (!i) {x = 0 ; y = p;return;} if (i == sum[p]) {x = p ; y = 0;return;} pushdown(p); if (sum[l[p]] >= i) { y = p; split(l[p] , x , l[y] , i); pushup(y); } else { x = p; split(r[p] , r[x] , y , i - sum[l[p]] - 1); pushup(x); } } int __query(int x , int a , int b) { if (a == 1 && b == sum[x]) return mn[x]; pushdown(x); int u = sum[l[x]] + 1; int p = (a <= u && u <= b ? key[x] : 1 << 30); if (a < u) p = min(p , __query(l[x] , a , b >= u ? u - 1 : b)); if (b > u) p = min(p , __query(r[x] , a <= u ? 1 : a - u , b - u)); return p; } int query(int a , int b) {return __query(root , a , b);} int Reverse(int a , int b) { int x , y , z; split(root , x , y , a - 1); split(y , y , z , b - a + 1); rev[y] ^= 1 , swap(l[y] , r[y]); merge(x , x , y); merge(root , x , z); } int Add(int a , int b , int c) { int x , y , z; split(root , x , y , a - 1); split(y , y , z , b - a + 1); key[y] += c , mn[y] += c , add[y] += c; merge(x , x , y); merge(root , x , z); } int Revolve(int a , int b , int c) { int w , x , y , z; split(root , w , x , a - 1); split(x , x , y , b - a + 1); split(y , y , z , c - b); merge(w , w , y); merge(w , w , x); merge(root , w , z); } }; Segment_Treap T; void work() { int n , i , x , y , z , m; char str[50]; scanf("%d",&n);T.clear(); for (i = 1 ; i <= n ; ++ i) scanf("%d",&x) , T.insert(i , x); scanf("%d",&m); while (m --) { scanf("%s" , str); if (*str == 'A') { scanf("%d%d%d",&x,&y,&z); T.Add(x , y , z); }else if (*str == 'I') { scanf("%d%d",&x,&y); T.insert(x + 1 , y); }else if (*str == 'D') { scanf("%d",&x); T.erase(x); }else if (*str == 'M') { scanf("%d%d",&x,&y); printf("%d\n" , T.query(x , y)); }else if (*(str + 3) == 'E') { scanf("%d%d",&x,&y); T.Reverse(x , y); }else { scanf("%d%d%d",&x,&y,&z); z = (z % (y - x + 1) + y - x + 1) % (y - x + 1); if (z) T.Revolve(x , y - z , y); } } } int main() { work(); return 0; }
完全就是套上面那道题啦。。
代码就不贴了
BZOJ1269 [AHOI2006]文本编辑器editor
http://www.lydsy.com/JudgeOnline/problem.php?id=1269
题目都差不多,只是发现带垃圾回收的版本比不带的快好多,只要空间开足够就好。
Segment_Treap T; void work() { int n , i , x , y , z , m; char str[50] , c; scanf("%d",&m); int pos = 0; while (m --) { scanf("%s" , str); if (*str == 'I') { scanf("%d",&n);getchar(); x = 0; for (i = 1 ; i <= n ; ++ i) { c = getchar(); T.__insert(x , i , c); } T.split(T.root , y , z , pos); T.merge(y , y , x); T.merge(T.root , y , z); } if (*str == 'M') scanf("%d",&pos); if (*str == 'D') { scanf("%d",&x); T.split(T.root , y , z , pos); T.split(z , i , z , x); T.merge(T.root , y , z); } if (*str == 'R') { scanf("%d",&x); T.Reverse(pos + 1 , pos + x); } if (*str == 'P') -- pos; if (*str == 'N') ++ pos; if (*str == 'G') printf("%c\n" , T.query(pos + 1)); } }
BZOJ1507: [NOI2003]Editor
样例第二条Move 16是错的,应该是Move 15
然后调了半天……然后就没什么了
Segment_Treap T; void work() { int n , i , x , y , z , m; char str[50] , c; //T.clear(); scanf("%d",&m); int pos = 0; while (m --) { scanf("%s" , str); if (*str == 'I') { scanf("%d",&n);getchar(); x = 0; for (i = 1 ; i <= n ; ++ i) { c = getchar(); if (c == '\n' || c == '\r') {-- i;continue;} T.__insert(x , i , c); } T.split(T.root , y , z , pos); T.merge(y , y , x); T.merge(T.root , y , z); } if (*str == 'M') scanf("%d",&pos); if (*str == 'D') { scanf("%d",&x); T.split(T.root , y , z , pos); T.split(z , i , z , x); //T.__delete(i); T.merge(T.root , y , z); } if (*str == 'P') -- pos; if (*str == 'N') ++ pos; if (*str == 'G') { scanf("%d",&x); T.split(T.root , y , z , pos); T.split(z , i , z , x); T.__puts(i);puts(""); T.merge(z , i , z); T.merge(T.root , y , z); } } }
BZOJ1500: [NOI2005]维修数列
http://www.lydsy.com/JudgeOnline/problem.php?id=1500
本机挺快AC但是OJ疯狂TLE。。有什么强大的数据?
好吧发现splay速度是我这个Treap的3倍以上QAQ
#include <iostream> #include <cstdio> #include <vector> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <cstdlib> #include <ctime> using namespace std; #define N 100005 #define M 500005 struct Segment_Treap { int nodecnt , root; int key[M] ; unsigned int priority[M] ; int sum[M] , cnt[M]; int l[M] , r[M]; int lm[M] , rm[M] , sm[M]; int del , sz[M]; bool rev[M] , same[M]; void pushdown(int x) { if (rev[x]) { if(l[x]) swap(l[l[x]] , r[l[x]]) , rev[l[x]] ^= 1 , swap(lm[l[x]] , rm[l[x]]); if(r[x]) swap(l[r[x]] , r[r[x]]) , rev[r[x]] ^= 1 , swap(lm[r[x]] , rm[r[x]]); rev[x] ^= 1; } if (same[x]) { if(l[x]) same[l[x]] = 1 , key[l[x]] = key[x] , cnt[l[x]] = key[x] * sum[l[x]] , lm[l[x]] = rm[l[x]] = sm[l[x]] = max(key[x] , cnt[l[x]]); if(r[x]) same[r[x]] = 1 , key[r[x]] = key[x] , cnt[r[x]] = key[x] * sum[r[x]] , lm[r[x]] = rm[r[x]] = sm[r[x]] = max(key[x] , cnt[r[x]]); same[x] = 0; } } void pushup(int x) { cnt[x] = key[x] , sum[x] = 1; lm[x] = cnt[l[x]] + max(key[x] , 0), rm[x] = cnt[r[x]] + max(key[x] , 0) , sm[x] = max(lm[r[x]] , 0) + key[x] + max(rm[l[x]] , 0); if(l[x]) lm[x] = max(lm[x] , lm[l[x]]) , rm[x] = max(rm[x] , cnt[r[x]] + key[x] + rm[l[x]]) , sm[x] = max(sm[x] , sm[l[x]]) , cnt[x] += cnt[l[x]] , sum[x] += sum[l[x]]; if(r[x]) rm[x] = max(rm[x] , rm[r[x]]) , lm[x] = max(lm[x] , cnt[l[x]] + key[x] + lm[r[x]]) , sm[x] = max(sm[x] , sm[r[x]]) , cnt[x] += cnt[r[x]] , sum[x] += sum[r[x]]; } void __insert(int& x , int i , int k) { if (x) { pushdown(x); if (sum[l[x]] + 1 >= i) { __insert(l[x] , i , k); int y = l[x]; if (priority[y] < priority[x]) { pushdown(y); l[x] = r[y] , r[y] = x , x = y; pushup(r[x]); } } else { __insert(r[x] , i - sum[l[x]] - 1 , k); int y = r[x]; if (priority[y] < priority[x]) { pushdown(y); r[x] = l[y] , l[y] = x , x = y; pushup(l[x]); } } } else { if (del) x = sz[del --];else x = ++ nodecnt; cnt[x] = key[x] = k , sum[x] = 1; lm[x] = rm[x] = sm[x] = cnt[x]; same[x] = rev[x] = 0; priority[x] = rand(); l[x] = r[x] = 0; } pushup(x); } void merge(int& p , int x , int y) { if (!x || !y) p = x | y; else if (priority[x] < priority[y]) pushdown(x) , merge(r[x] , r[x] , y) , pushup(x) , p = x; else pushdown(y) , merge(l[y] , x , l[y]) , pushup(y) , p = y; } void split(int p , int& x , int& y , int i) { if (!i) {x = 0 ; y = p;return;} if (i == sum[p]) {x = p ; y = 0;return;} pushdown(p); if (sum[l[p]] >= i) { y = p; split(l[p] , x , l[y] , i); pushup(y); } else { x = p; split(r[p] , r[x] , y , i - sum[l[p]] - 1); pushup(x); } } void bye(int x) { if(l[x]) bye(l[x]); sz[++ del] = x; if(r[x]) bye(r[x]); } int __query(int x , int a , int b) { if (a == 1 && b == sum[x]) return cnt[x]; pushdown(x); int u = sum[l[x]] + 1; int p = (a <= u && u <= b ? key[x] : 0); if (a < u) p += __query(l[x] , a , b >= u ? u - 1 : b); if (b > u) p += __query(r[x] , a <= u ? 1 : a - u , b - u); return p; } }; Segment_Treap T; int Get() { char c=getchar(); int ret=0; while ((c!='-')&&((c<'0')||(c>'9'))) c=getchar(); if (c=='-') return -Get(); while ((c>='0')&&(c<='9')) ret=ret*10+c-'0',c=getchar(); return ret; } void work() { int n , i , j , x , y , z , m; char str[20]; n = Get() , m = Get(); for (i = 1 ; i <= n ; ++ i) x = Get() , T.__insert(T.root , i , x); while (m --) { scanf("%s" , str); if (*str == 'I') { y = Get() ; n = Get(); x = 0; for (i = 1 ; i <= n ; ++ i) z = Get() , T.__insert(x , i , z); T.split(T.root , j , z , y); T.merge(j , j , x); T.merge(T.root , j , z); continue; } if (*str == 'D') { i = Get() ; j = Get(); T.split(T.root , x , y , i - 1); T.split(y , y , z , j); T.bye(y); T.merge(T.root , x , z);continue; } if (*(str + 2) == 'K') { i = Get() ; j = Get(); n = Get(); T.split(T.root , x , y , i - 1); T.split(y , y , z , j); T.key[y] = n , T.same[y] = 1 , T.cnt[y] = T.sum[y] * n; T.lm[y] = T.rm[y] = T.sm[y] = max(T.cnt[y] , n); T.merge(y , y , z); T.merge(T.root , x , y);continue; } if (*str == 'R') { i = Get() ; j = Get(); T.split(T.root , x , y , i - 1); T.split(y , y , z , j); T.rev[y] ^= 1 , swap(T.l[y] , T.r[y]) , swap(T.lm[y] , T.rm[y]); T.merge(y , y , z); T.merge(T.root , x , y);continue; } if (*str == 'G') { i = Get() ; j = Get(); printf("%d\n" , T.__query(T.root , i , i + j - 1));continue; } if (*(str + 2) == 'X') printf("%d\n" , T.sm[T.root]); } } int main() { freopen("sequence.in","r",stdin); freopen("sequence.out","w",stdout); work(); return 0; }
Splay版,因为一个白痴问题调了很久……
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define N 500005 int a[N]; struct splay_tree { int root , nodecnt , c[N][2] , size[N] , par[N] , type[N] , stack[N]; int key[N] , sum[N] , lm[N] , rm[N] , sm[N] , same[N]; bool rev[N]; int rub[N] , rs; void clear() { root = 0 , size[0] = 0; c[0][0] = c[0][1] = par[0] = 0; rev[0] = 0 , same[0] = 1 << 30; nodecnt = 0; } int malloc(int k) { int x; if (rs) x = rub[rs --]; else x = ++ nodecnt; sum[x] = key[x] = k , size[x] = 1 , type[x] = -1; lm[x] = rm[x] = sm[x] = key[x]; same[x] = 1 << 30 , rev[x] = 0; c[x][0] = c[x][1] = par[x] =0; return x; } void pushdown(int x) { if (rev[x]) { swap(lm[x] , rm[x]) , swap(c[x][0] , c[x][1]); if(c[x][0]) rev[c[x][0]] ^= 1 , type[c[x][0]] = 0; if(c[x][1]) rev[c[x][1]] ^= 1 , type[c[x][1]] = 1; rev[x] ^= 1; } if (same[x] != 1 << 30) { key[x] = same[x] , sum[x] = key[x] * size[x]; lm[x] = rm[x] = sm[x] = max(key[x] , sum[x]); if(c[x][0]) same[c[x][0]] = same[x]; if(c[x][1]) same[c[x][1]] = same[x]; same[x] = 1 << 30; } } void pushup(int x) { if (!x) return; pushdown(x); pushdown(c[x][0]); pushdown(c[x][1]); sum[x] = key[x] , size[x] = 1; lm[x] = sum[c[x][0]] + max(key[x] , 0), rm[x] = sum[c[x][1]] + max(key[x] , 0) , sm[x] = max(lm[c[x][1]] , 0) + key[x] + max(rm[c[x][0]] , 0); if(c[x][0]) lm[x] = max(lm[x] , lm[c[x][0]]) , rm[x] = max(rm[x] , sum[c[x][1]] + key[x] + rm[c[x][0]]) , sm[x] = max(sm[x] , sm[c[x][0]]) , sum[x] += sum[c[x][0]] , size[x] += size[c[x][0]]; if(c[x][1]) rm[x] = max(rm[x] , rm[c[x][1]]) , lm[x] = max(lm[x] , sum[c[x][0]] + key[x] + lm[c[x][1]]) , sm[x] = max(sm[x] , sm[c[x][1]]) , sum[x] += sum[c[x][1]] , size[x] += size[c[x][1]]; } void rotate (int x) { int t = type[x] , y = par[x] , z = c[x][t ^ 1]; type[x] = type[y] , par[x] = par[y]; if (~type[x]) c[par[x]][type[x]] = x; type[y] = t ^ 1 , par[y] = x , c[x][t ^ 1] = y; if (x) type[z] = t , par[z] = y; c[y][t] = z , pushup(y); } void splay(int x) { int cnt = 0 , i; stack[++ cnt] = x; for (i = x ; ~type[i] ; i = par[i]) stack[++ cnt] = par[i]; for (i = cnt ; i > 0 ; -- i) pushdown(stack[i]); while (~type[x]) { int y = par[x]; if (type[x] == type[y])rotate(y) ;else rotate(x); if (!~type[x]) break; rotate(x); } pushup(x); } int getKth(int x , int k) { while (1) { pushdown(x); if (size[c[x][0]] + 1 == k) break; if (size[c[x][0]] + 1 > k) x = c[x][0]; else k -= size[c[x][0]] + 1 , x = c[x][1]; } return x; } void split(int p , int& x , int& y , int a) { if (a == size[p]) {x = p , y = 0;return;} y = getKth(p , a + 1) , splay(y); x = c[y][0] , type[x] = -1 , c[y][0] = 0 , par[x] = 0; pushup(y); } void merge(int& p , int x ,int y) { if (!x || !y) {p = x | y ; return;} pushdown(x); p = getKth(x , size[x]) , splay(p) , c[p][1] = y; type[y] = 1 , par[y] = p , pushup(p); } int Build(int l , int r) { if (l > r) return 0; int m = (l + r) >> 1; int x = malloc(a[m]); c[x][0] = Build(l , m - 1) ;if(c[x][0]) type[c[x][0]] = 0 , par[c[x][0]] = x; c[x][1] = Build(m + 1 , r) ;if(c[x][1]) type[c[x][1]] = 1 , par[c[x][1]] = x; pushup(x);return x; } void del(int x) { if (c[x][0]) del(c[x][0]); rub[++ rs] = x; if (c[x][1]) del(c[x][1]); } void print(int x) { pushdown(x); if (c[x][0]) print(c[x][0]); printf("%d ", key[x]); if (c[x][1]) print(c[x][1]); } }; splay_tree T; int main() { freopen("sequence.in","r",stdin); freopen("sequence.out","w",stdout); int n , m , x , y , z , l , r , i; char str[20]; T.clear(); scanf("%d%d",&n,&m); for (i = 1 ; i <= n ; ++ i) scanf("%d",&a[i]); T.root = T.Build(1 , n); while (m --) { scanf("%s" , str); if (*(str + 2) == 'X') printf("%d\n" , T.sm[T.root]); else if (*str == 'I') { scanf("%d%d",&l,&n); T.split(T.root , x , y , l); for (i = 1 ; i <= n ; ++ i) scanf("%d",&a[i]); z = T.Build(1 , n); T.merge(x , x , z); T.merge(T.root , x , y); } else { scanf("%d%d",&l,&r); T.split(T.root , x , y , l - 1); T.split(y , y , z , r); if (*str == 'G') printf("%d\n" , T.sum[y]); if (*str == 'D') T.del(y) , T.merge(T.root , x , z); if (*str == 'M') scanf("%d",&T.same[y]); if (*str == 'R') T.rev[y] ^= 1; if (*str != 'D') T.merge(y , y , z) , T.merge(T.root , x , y); } } return 0; }