NOI2005维修数列 splay
好题,错了不知道多少遍。这题其他几个操作都是比较经典的,多了一个最大子序列的。这时候对于当前的区间,最大子序列,可能使左区间的最值,可能是右区间的最值,也可能是整个区间的。所以维护lx[],rx[],mx[]。lx[rt] = max(lx[l],sum[l]+key[rt]+max(0,lx[r]));当前节点的左区间最值可能是左孩子的最值,也可能是左孩子加右孩子的一部分。
rx[]类似。mx[rt] = max(0,rx[l])+key[rt]+max(0,lx[r]);mx[rt] = max(mx[rt],max(mx[l],mx[r]));
#include<queue> #include<stack> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define INF 99999999 #define ll __int64 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define key_value ch[ch[root][1]][0] using namespace std; const int MAXN = 900005; int pre[MAXN],ch[MAXN][2],siz[MAXN],sum[MAXN],rev[MAXN],lazy[MAXN],key[MAXN],root,tot1; int n,a[MAXN],cnt,s[MAXN],tot2; int mx[MAXN],lx[MAXN],rx[MAXN]; void Treavel(int x) { if(x) { Treavel(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d key=%2d lazy=%2d rev=%2d siz[0]=%2d\n",x,ch[x][0],ch[x][1],pre[x],siz[x],key[x],lazy[x],rev[x],siz[0]); Treavel(ch[x][1]); } } void debug() { printf("root:%d\n",root); Treavel(root); } void Newnode(int &rt,int pa,int k) { if(tot2){ rt = s[tot2--]; } else { rt = ++tot1; } pre[rt] = pa; sum[rt] = k; rev[rt] = 0; lazy[rt] = 0; siz[rt] = 1; key[rt] = lx[rt] = rx[rt] = mx[rt] = k; ch[rt][0] = ch[rt][1] = 0; } void pushup(int rt) { int l = ch[rt][0]; int r = ch[rt][1]; siz[rt] = siz[l] + siz[r] + 1; sum[rt] = sum[l] + sum[r] + key[rt]; lx[rt] = max(lx[l],sum[l]+key[rt]+max(0,lx[r])); rx[rt] = max(rx[r],sum[r]+key[rt]+max(0,rx[l])); mx[rt] = max(0,rx[l]) + key[rt] + max(0,lx[r]); mx[rt] = max(mx[rt],max(mx[l],mx[r])); } void updata_same(int rt,int k) { if(!rt) return ; key[rt] = k; sum[rt] = k*siz[rt]; lx[rt] = rx[rt] = mx[rt] = max(k,k*siz[rt]); lazy[rt] = 1; } void updata_rev(int rt) { rev[rt] ^= 1; swap(ch[rt][0],ch[rt][1]); swap(lx[rt],rx[rt]); } void pushdown(int rt) { if(lazy[rt]){ updata_same(ch[rt][0],key[rt]); updata_same(ch[rt][1],key[rt]); lazy[rt] = 0; } if(rev[rt]){ updata_rev(ch[rt][0]); updata_rev(ch[rt][1]); rev[rt] = 0; } } void build(int &rt,int l,int r,int pa) { if(l > r){ return ; } int m = (l+r)/2; Newnode(rt,pa,a[m]); build(ch[rt][0],l,m-1,rt); build(ch[rt][1],m+1,r,rt); pushup(rt); } void Init() { root = tot1 = tot2 = 0; pre[root] = sum[root] = key[root] = lazy[root] = rev[root] = siz[root] = 0; lx[root] = rx[root] = mx[root] = -INF;//重要 ch[root][0] = ch[root][1] = 0; Newnode(root,0,0); Newnode(ch[root][1],root,0); build(key_value,1,n,ch[root][1]); pushup(ch[root][1]); pushup(root); } int Get_kth(int rt,int k) { pushdown(rt); int t = siz[ch[rt][0]] + 1; if(t == k){ return rt; } else if(t > k){ return Get_kth(ch[rt][0],k); } else { return Get_kth(ch[rt][1],k-t); } } void Rotate(int rt,int kind) { int y = pre[rt]; pushdown(y); pushdown(rt); ch[y][!kind] = ch[rt][kind]; pre[ch[rt][kind]] = y; if(pre[y]){ ch[pre[y]][ch[pre[y]][1]==y] = rt; } pre[rt] = pre[y]; ch[rt][kind] = y; pre[y] = rt; pushup(y); } void splay(int rt,int goal) { pushdown(rt); while(pre[rt] != goal) { if(pre[pre[rt]] == goal){ pushdown(pre[rt]); pushdown(rt); Rotate(rt,ch[pre[rt]][0]==rt); } else { pushdown(pre[pre[rt]]); pushdown(pre[rt]); pushdown(rt); int y = pre[rt]; int kind = ch[pre[y]][0]==y; if(ch[y][kind] == rt){ Rotate(rt,!kind); Rotate(rt,kind); } else { Rotate(y,kind); Rotate(rt,kind); } } } if(goal == 0) root = rt; pushup(rt); } void erase(int rt) { if(!rt) return; s[++tot2] = rt; erase(ch[rt][0]); erase(ch[rt][1]); } int main() { int m,i,j; while(scanf("%d%d",&n,&m)!=EOF) { for(i=1; i<=n; i++){ scanf("%d",&a[i]); } Init(); char c[20]; while(m--) { scanf("%s",c); if(c[0] == 'I'){ int x,y; scanf("%d%d",&x,&y); for(i=1; i<=y; i++){ scanf("%d",&a[i]); } splay(Get_kth(root,x+1),0); splay(Get_kth(root,x+2),root); build(key_value,1,y,ch[root][1]); pushup(ch[root][1]); pushup(root); } else if(c[0] == 'D'){ int x,y; scanf("%d%d",&x,&y); splay(Get_kth(root,x),0); splay(Get_kth(root,x+y+1),root); erase(key_value); pre[key_value] = 0; key_value = 0; pushup(ch[root][1]); pushup(root); } else if(c[0] == 'M' && c[2] == 'K'){ int x,y,z; scanf("%d%d%d",&x,&y,&z); splay(Get_kth(root,x),0); splay(Get_kth(root,x+y+1),root); updata_same(key_value,z); pushup(ch[root][1]); pushup(root); } else if(c[0] == 'R'){ int x,y; scanf("%d%d",&x,&y); splay(Get_kth(root,x),0); splay(Get_kth(root,x+y+1),root); updata_rev(key_value); pushup(ch[root][1]); pushup(root); } else if(c[0] == 'G'){ int x,y; scanf("%d%d",&x,&y); splay(Get_kth(root,x),0); splay(Get_kth(root,x+y+1),root); printf("%d\n",sum[key_value]); } else{ splay(Get_kth(root,1),0); splay(Get_kth(root,siz[root]),root); printf("%d\n",mx[key_value]); } } } }