BZOJ1500: [NOI2005]维修数列 [splay序列操作]【学习笔记】
以前写过这道题了,但我把以前的内容删掉了,因为现在感觉没法看
重写!
题意:
维护一个数列,支持插入一段数,删除一段数,修改一段数,翻转一段数,查询区间和,区间最大子序列
splay序列操作裸题
需要回收节点编号,所以用到$sz和nw()$,通常维护序列是不用sz的
splay维护的是这个序列,不再存在平衡树左小右大的性质
操作一段区间$[l,r]$,将$l-1\ splay$到根,$r+1\ splay$到右孩子,他的左孩子就是要操作的区间
为了方便加入两个哨兵节点
注意splay和线段树不同,每个节点都代表了一个元素
对于本题来说,因为有可能是修改成0或负数,所以tag=1表示执行了修改操作而不是修改成什么
下传标记修改会覆盖查询,无论时间先后
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define lc t[x].ch[0] #define rc t[x].ch[1] #define pa t[x].fa typedef long long ll; const int N=5e5, INF=1e9; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} return x*f; } int n, Q, a[N], k, tot; char s[20]; struct meow{ int ch[2], fa, size, v, sum, mx, lm, rm, tag, rev; meow() {} meow(int val) {ch[0]=ch[1]=fa=tag=rev=0; size=1; v=sum=mx=lm=rm=val;} }t[N]; int root, sz; inline int wh(int x) {return t[pa].ch[1] == x;} int st[N], top; inline int nw() {return top ? st[top--] : ++sz;} inline void paint(int x,int v) { t[x].tag = 1; t[x].v = v; t[x].sum = t[x].size*v; t[x].mx = t[x].lm = t[x].rm = max(t[x].sum, v); t[x].rev = 0; } inline void rever(int x) { if(t[x].tag) return; //hi t[x].rev^=1; swap(lc, rc); swap(t[x].lm, t[x].rm); } inline void pushDown(int x) { if(t[x].rev) { if(lc) rever(lc); if(rc) rever(rc); t[x].rev=0; } if(t[x].tag) { if(lc) paint(lc, t[x].v); if(rc) paint(rc, t[x].v); t[x].tag=0; } } inline void update(int x) { t[x].size = t[lc].size + t[rc].size + 1; t[x].sum = t[lc].sum + t[rc].sum + t[x].v; t[x].mx = max(max(t[lc].mx, t[rc].mx), max(0, t[lc].rm) + t[x].v + max(0, t[rc].lm) ); t[x].lm = max(t[lc].lm, t[lc].sum + t[x].v + max(0, t[rc].lm) ); t[x].rm = max(t[rc].rm, t[rc].sum + t[x].v + max(0, t[lc].rm) ); } inline void rotate(int x) { int f=t[x].fa, g=t[f].fa, c=wh(x); if(g) t[g].ch[wh(f)]=x; t[x].fa=g; t[f].ch[c] = t[x].ch[c^1]; t[t[f].ch[c]].fa=f; t[x].ch[c^1]=f; t[f].fa=x; update(f); update(x); } inline void splay(int x,int tar) { for(; pa!=tar; rotate(x)) if(t[pa].fa != tar) rotate(wh(x)==wh(pa) ? pa : x); if(tar==0) root=x; } void build(int &x,int l,int r,int f) { int mid = (l+r)>>1; x=nw(); t[x]=meow(a[mid]); t[x].fa=f; if(l==r) return; if(l<mid) build(lc, l, mid-1, x); if(mid<r) build(rc, mid+1, r, x); update(x); } inline int kth(int k) { int x=root, lsize=0; while(x) { pushDown(x); int _ = lsize + t[lc].size; if(k<=_) x=lc; else if(k<=_+1) return x; else lsize=_+1, x=rc; } return -1; } void Ins(int k, int tot) { for(int i=1; i<=tot; i++) a[i]=read(); int f=kth(k+1); splay(f, 0); int x=kth(k+2); splay(x, f); build(lc, 1, tot, x); update(x); update(f); } void erase(int x) { if(!x) return; st[++top]=x; erase(lc); erase(rc); } void Del(int k, int tot) { int f=kth(k); splay(f, 0); int x=kth(k+tot+1); splay(x, f); erase(lc); lc=0; update(x); update(f); } void Mak(int k, int tot) { int f=kth(k); splay(f, 0); int x=kth(k+tot+1); splay(x, f); paint(lc, read()); update(x); update(f); } void Rev(int k, int tot) { int f=kth(k); splay(f, 0); int x=kth(k+tot+1); splay(x, f); rever(lc); update(x); update(f); } int Sum(int k, int tot) { int f=kth(k); splay(f, 0); int x=kth(k+tot+1); splay(x, f); return t[lc].sum; } int main() { //freopen("in","r",stdin); n=read(); Q=read(); for(int i=2; i<=n+1; i++) a[i]=read(); a[1] = a[n+2] = -INF; t[0]=meow(-INF); t[0].sum=t[0].size=0; build(root, 1, n+2, 0); for(int i=1; i<=Q; i++) { //printf("Q %d\n",i); scanf("%s",s+1); if(s[3]=='X') printf("%d\n", t[root].mx); else { k=read(); tot=read(); if(s[1]=='I') Ins(k, tot); if(s[1]=='D') Del(k, tot); if(s[1]=='M') Mak(k, tot); if(s[1]=='R') Rev(k, tot); if(s[1]=='G') printf("%d\n", Sum(k, tot)); } } }
Copyright:http://www.cnblogs.com/candy99/