[NOI2005]维护数列_Splay
真的毫无算法可言,就是比谁的码力强罢了...
Code:
#include<stack> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 500000 + 200; const int inf = -1223; int ch[maxn][2], f[maxn], numv[maxn], maxv[maxn], lmax[maxn], rmax[maxn], sumv[maxn], tag[maxn], lazy[maxn],siz[maxn]; int root, arr[maxn]; stack <int> S; struct Operation { inline void init(){ for(int i = maxn - 10; i >= 1; --i) S.push(i); } inline int new_node(){ int u = S.top(); S.pop(); return u; } inline void erase(int x) { ch[x][0] = ch[x][1] = f[x] = 0; maxv[x] = numv[x] = lmax[x] = rmax[x] = sumv[x] = tag[x] = siz[x] = 0; lazy[x] = inf; } inline void trash(int u) { if(!u) return ; S.push(u); trash(ch[u][0]); trash(ch[u][1]); erase(u); } inline void pushup(int o) { int ls = ch[o][0], rs = ch[o][1]; maxv[o] = numv[o]; sumv[o] = sumv[ls] + sumv[rs] + numv[o]; siz[o] = siz[ls] + siz[rs] + 1; int sums = numv[o]; if(ls) maxv[o] = max(maxv[o], maxv[ls]), sums += rmax[ls]; if(rs) maxv[o] = max(maxv[o], maxv[rs]), sums += lmax[rs]; maxv[o] = max(maxv[o], sums); lmax[o] = max(lmax[ls], sumv[ls] + numv[o] + lmax[rs]); rmax[o] = max(rmax[rs], sumv[rs] + numv[o] + rmax[ls]); } inline void maintain(int o) { maxv[o] = max(numv[o], sumv[o]); lmax[o] = rmax[o] = max(0, sumv[o]); } inline void pushdown(int x) { int ls = ch[x][0], rs = ch[x][1]; if(lazy[x] != inf) { if(ls){ numv[ls] = lazy[ls] = lazy[x], sumv[ls] = siz[ls] * numv[ls]; maintain(ls); } if(rs){ numv[rs] = lazy[rs] = lazy[x], sumv[rs] = siz[rs] * numv[rs]; maintain(rs); } lazy[x] = inf; } if(tag[x]) { swap(lmax[ls], rmax[ls]); swap(lmax[rs], rmax[rs]); swap(ch[ls][0], ch[ls][1]); swap(ch[rs][0], ch[rs][1]); if(ls) tag[ls] ^= 1; if(rs) tag[rs] ^= 1; tag[x] = 0; } } void build(int l,int r,int fa,int &o) { if(l > r) return ; int mid = (l + r) >> 1; o = new_node(); f[o] = fa, numv[o] = arr[mid], lazy[o] = inf; build(l, mid - 1, o, ch[o][0]); build(mid + 1, r, o, ch[o][1]); pushup(o); } }T; inline int get(int x){ return ch[f[x]][1] == x;} inline void rotate(int x) { int old = f[x], oldf = f[old], which = get(x); ch[old][which] = ch[x][which ^ 1], f[ch[old][which]] = old; ch[x][which ^ 1] = old, f[old] = x, f[x] = oldf; if(oldf) ch[oldf][ch[oldf][1] == old] = x; T.pushup(old); T.pushup(x); } inline void splay(int x,int &tar) { int a = f[tar]; for(int fa; (fa = f[x]) != a; rotate(x)) if(f[fa] != a) rotate(get(x) == get(fa) ? fa : x); tar = x; } inline int findx(int x, int top) { int cur = top; while(1) { T.pushdown(cur); int ls = ch[cur][0]; if(x == siz[ls] + 1) return cur; if(x <= siz[ls]) cur = ch[cur][0]; else x -= siz[ls] + 1, cur = ch[cur][1]; } return 0; } inline void split(int &a, int nums, int &b) { if(nums == 0) { b = a, a = 0; return ; } if(nums == siz[a]) { b = 0; return ; } int u = findx(nums, a); splay(u, a); b = ch[a][1], f[ch[a][1]] = 0 , ch[a][1] = 0; T.pushup(a); } inline void merge(int &a, int &b) { if(!a) { a = b; return ; } int u = findx(siz[a], a); splay(u, a); ch[a][1] = b, f[ch[a][1]] = a; T.pushup(a); } inline void Insert() { int pos, tot; scanf("%d%d",&pos,&tot); for(int i = 1;i <= tot; ++i) scanf("%d",&arr[i]); int a = 0, b = 0; split(root, pos, a); T.build(1, tot, 0, b); merge(root, b); merge(root, a); } inline void Delete() { int pos, tot; scanf("%d%d",&pos,&tot); int a , b; split(root, pos - 1, a); split(a, tot, b); T.trash(a); merge(root, b); } inline void Make_Same() { int pos, tot, c, a = 0, b = 0; scanf("%d%d%d",&pos,&tot,&c); split(root, pos - 1, a), split(a, tot, b); sumv[a] = siz[a] * c, lazy[a] = c, numv[a] = c; T.maintain(a); merge(root, a), merge(root, b); } inline void Reverse() { int pos, tot, a = 0, b = 0; scanf("%d%d",&pos,&tot); split(root, pos - 1, a); split(a, tot, b); tag[a] ^= 1; swap(lmax[a], rmax[a]), swap(ch[a][0], ch[a][1]); merge(root, a), merge(root, b); } inline void Get_sum() { int pos, tot, a = 0, b = 0; scanf("%d%d",&pos,&tot); split(root, pos - 1, a), split(a, tot, b); printf("%d\n",sumv[a]); merge(root, a), merge(root, b); } int main() { int n,m; scanf("%d%d",&n,&m); T.init(); for(int i = 1;i <= n; ++i) scanf("%d",&arr[i]); T.build(1, n, 0, root); for(int i = 1;i <= m; ++i) { char str[30]; scanf("%s",str); if(str[0] == 'I') Insert(); if(str[0] == 'D') Delete(); if(str[2] == 'K') Make_Same(); if(str[0] == 'R') Reverse(); if(str[0] == 'G') Get_sum(); if(str[2] == 'X') printf("%d\n",maxv[root]); } return 0; }