BZOJ1500 [NOI2005]维修数列(Splay)
2016-04-08 11:38
435 查看
题意不多说。这大概算是splay的终极题目了吧,和poj3580差不多。
插入:把左端点前一个节点和右端点后一个节点旋转到根和根的右儿子,然后像建树那样构造右儿子的左子树。
删除:同上的旋转方式。删掉根节点的右儿子的左子树。虽然同时存在的节点不超过500 000个,但是不停的插入删除会使节点编号x变得非常大,造成RE;因此需要内存回收,开一个栈来保存删掉的所有节点编号。
修改:同上的旋转方式。在右儿子左子树打好懒标记。
翻转:同上的旋转方式。同样在右儿子左子树打好懒标记。
求和:同上的旋转方式。输出右儿子左子树代表的区间的和。
求最大和的子序列:需要保存区间从左端点的最大和子序列lmx,从右向左的rmx,还有区间最大的和子序列mx。那么该区间的从左向右的最大和子序列就是它左儿子的从左向右的最大和子序列,或者是左儿子的和加上v[x]以及右儿子从左向右的最大和子序列,也就是lmx[x]=Max(lmx[lch],sum[lch]+v[x]+lmx[rch])lmx[x] = Max(lmx[lch],sum[lch]+v[x]+lmx[rch]),rmx的求法同理。区间的最大子序列和可以在左右子树,也可以在中间,那么有mx[x]=Max(mx[lch],mx[rch],rmx[lch]+v[x]+lmx[rch])mx[x] = Max(mx[lch],mx[rch],rmx[lch]+v[x]+lmx[rch])
插入:把左端点前一个节点和右端点后一个节点旋转到根和根的右儿子,然后像建树那样构造右儿子的左子树。
删除:同上的旋转方式。删掉根节点的右儿子的左子树。虽然同时存在的节点不超过500 000个,但是不停的插入删除会使节点编号x变得非常大,造成RE;因此需要内存回收,开一个栈来保存删掉的所有节点编号。
修改:同上的旋转方式。在右儿子左子树打好懒标记。
翻转:同上的旋转方式。同样在右儿子左子树打好懒标记。
求和:同上的旋转方式。输出右儿子左子树代表的区间的和。
求最大和的子序列:需要保存区间从左端点的最大和子序列lmx,从右向左的rmx,还有区间最大的和子序列mx。那么该区间的从左向右的最大和子序列就是它左儿子的从左向右的最大和子序列,或者是左儿子的和加上v[x]以及右儿子从左向右的最大和子序列,也就是lmx[x]=Max(lmx[lch],sum[lch]+v[x]+lmx[rch])lmx[x] = Max(lmx[lch],sum[lch]+v[x]+lmx[rch]),rmx的求法同理。区间的最大子序列和可以在左右子树,也可以在中间,那么有mx[x]=Max(mx[lch],mx[rch],rmx[lch]+v[x]+lmx[rch])mx[x] = Max(mx[lch],mx[rch],rmx[lch]+v[x]+lmx[rch])
#include<cstdio> #include<cstring> #include<cctype> #define MAXN 500010 #define INF 0x3f3f3f3f #define key_pos ch[ch[root][1]][0] using namespace std; inline int Max(int a,int b) {return a>b?a:b;} inline int Min(int a,int b) {return a<b?a:b;} inline void Swap(int &a,int &b) {int c = a; a = b; b = c;} inline void GET(int &t) { char c; int f = 1; t = 0; do{c = getchar(); if(c == '-') f = -1;}while(!isdigit(c)); while(isdigit(c)) {t = t*10+c-'0'; c = getchar();} t *= f; } int ch[MAXN][2],v[MAXN],fa[MAXN],sz[MAXN]; int lz[MAXN],rev[MAXN],sum[MAXN],mxlen[MAXN],lmx[MAXN],rmx[MAXN]; int n,m,root,tot1,tot2,s[MAXN],a[MAXN]; void New(int &x,int father,int val) { if(tot2) x = s[tot2--]; else x = ++tot1; fa[x] = father; v[x] = sum[x] = mxlen[x] = lmx[x] = rmx[x] = val; sz[x] = 1; ch[x][0] = ch[x][1] = rev[x] = 0; lz[x] = INF; } void up_same(int x,int val) { if(!x) return; v[x] = val; sum[x] = val*sz[x]; mxlen[x] = lmx[x] = rmx[x] = Max(val,val*sz[x]); lz[x] = val; } void up_rev(int x) { if(!x) return; Swap(ch[x][0],ch[x][1]); Swap(lmx[x],rmx[x]); rev[x] ^= 1; } void pushup(int x) { int lch = ch[x][0],rch = ch[x][1],l = Max(0,lmx[rch]),r = Max(0,rmx[lch]); sz[x] = sz[lch]+sz[rch]+1; sum[x] = sum[rch]+sum[lch]+v[x]; lmx[x] = Max(lmx[lch],sum[lch]+v[x]+l); rmx[x] = Max(rmx[rch],sum[rch]+v[x]+r); mxlen[x] = Max(mxlen[lch],mxlen[rch]); mxlen[x] = Max(mxlen[x],l+r+v[x]); } void pushdown(int x) { if(lz[x] != INF) { up_same(ch[x][0],v[x]); up_same(ch[x][1],v[x]); lz[x] = INF; } if(rev[x]) { up_rev(ch[x][0]); up_rev(ch[x][1]); rev[x] = 0; } } void build(int &x,int L,int R,int father) { int mid = (L+R)/2; New(x,father,a[mid]); if(L == R) return; if(L < mid) build(ch[x][0],L,mid-1,x); if(R > mid) build(ch[x][1],mid+1,R,x); pushup(x); } void Init() { GET(n); GET(m); lmx[root] = rmx[root] = mxlen[root] = -INF; New(root,0,-1); New(ch[root][1],root,-1); for(int i = 0; i < n; i++) GET(a[i]); build(key_pos,0,n-1,ch[root][1]); pushup(ch[root][1]); pushup(root); } void rotate(int x) { int y = fa[x],z = fa[y],f = (ch[y][1] == x); ch[y][f] = ch[x][!f]; if(ch[y][f]) fa[ch[y][f]] = y; ch[x][!f] = y,fa[y] = x; fa[x] = z; if(z) ch[z][ch[z][1]==y] = x; pushup(y); } void splay(int x,int goal) { for(int y; (y=fa[x]) != goal; rotate(x)) { int z = fa[y]; if(z != goal) { if((ch[z][0] == y) == (ch[y][0] == x)) rotate(y); else rotate(x); } } if(!goal) root = x; pushup(x); } void rotateTo(int k,int goal) { int x = root; while(1) { pushdown(x); if(sz[ch[x][0]]+1 < k) k -= sz[ch[x][0]]+1,x = ch[x][1]; else if(sz[ch[x][0]]+1 > k) x = ch[x][0]; else break; } splay(x,goal); } void Insert(int pos,int tot) { for(int i = 0; i < tot; i++) GET(a[i]); rotateTo(pos+1,0); rotateTo(pos+2,root); build(key_pos,0,tot-1,ch[root][1]); pushup(ch[root][1]); pushup(root); } void Back(int x) { if(!x) return; s[++tot2] = x; Back(ch[x][0]); Back(ch[x][1]); } void Delete(int pos,int tot) { rotateTo(pos,0); rotateTo(pos+tot+1,root); Back(key_pos); fa[key_pos] = 0; key_pos = 0; pushup(ch[root][1]); pushup(root); } void Make_same(int pos,int tot,int val) { rotateTo(pos,0); rotateTo(pos+tot+1,root); up_same(key_pos,val); pushup(ch[root][1]); pushup(root); } void Reverse(int pos,int tot) { rotateTo(pos,0); rotateTo(pos+tot+1,root); up_rev(key_pos); pushup(ch[root][1]); pushup(root); } int Get_sum(int pos,int tot) { rotateTo(pos,0); rotateTo(pos+tot+1,root); return sum[key_pos]; } int Get_max(int pos,int tot) { rotateTo(pos,0); rotateTo(pos+tot+1,root); return mxlen[key_pos]; } int main() { char ops[20]; Init(); for(int i = 1,x,y,z; i <= m; i++) { scanf("%s",ops); if(ops[0] == 'I') {GET(x),GET(y); Insert(x,y);} else if(ops[0] == 'D') {GET(x),GET(y); Delete(x,y);} else if(ops[2] == 'K') {GET(x),GET(y),GET(z); Make_same(x,y,z);} else if(ops[0] == 'R') {GET(x),GET(y); Reverse(x,y);} else if(ops[0] == 'G') {GET(x),GET(y); printf("%d\n",Get_sum(x,y));} else printf("%d\n",Get_max(1,sz[root]-2)); } }
相关文章推荐
- requests.exceptions.ConnectionError: ('Connection aborted.', BadStatusLine("''",))
- c++第三次上机实验--静态成员函数
- 《Effective C++》阅读笔记03
- Android动态设置字体颜色
- MongoDB副本集集群
- iOS之sqlite3数据库介绍(附代码)
- anroid学习目录总结
- Linux Shell的 & 、&& 、 ||
- shell后台执行指令&
- EXPLAIN 命令详解
- spring mvc+ajax 问转调查传参处理
- 察人省己--項目關鍵4要素
- GitHub 上排名前 100 的 Android 开源库介绍
- pylab画柱状图
- hisi平台mii网络模式和rmii网络模式的uboot制作
- 《疯狂java讲义》笔记 1-5章
- 安卓手机获取手机通话记录信息
- 解读UIL图片缓存以及自己构建内存缓存
- tomcat
- 解决list.remove(object)问题