【NOI2005】【splay】维护数列
来源:互联网 发布:临床医学生必备软件 编辑:程序博客网 时间:2024/05/18 01:49
这题貌似比operation还要恶心一点。。。
为了练习splay硬着头皮写的,虽然现在AC了但我还是完全没有信心能够在考场上写出来,细节太多,下面进入正题。
1、最大序列和的询问,仿照线段树,需要维护Max,Maxl,Maxr,sum这几个量,在上传的时候更新。
2、由于内存限制,需要回收内存的操作,就是将下标回收进入一个数组,具体见代码。
3、标记要向下传递两层。(Ps:这个我也不知道为什么,我在这里卡了很久)
4、两个虚拟节点以及Max的初始值为-inf
5、不要将lazy标记与lazy标记的值合并,多开一个bool来标记
这道题的trick暂时就想到这些,至于其他的操作就与一般的splay维护数列的题无异了。
代码:
#include<cstdio>#include<algorithm>#include<cstring>#define keyTree ch[ ch[root][1] ][0]using namespace std;const int inf = 0x3f3f3f3f;const int maxn = 550000 + 10;const int bh = maxn - 10;struct SplayTree{ int ch[maxn][2],pre[maxn],num[maxn]; int ss[maxn],que[maxn]; int val[maxn],sum[maxn],sz[maxn]; int Maxl[maxn],Maxr[maxn],Max[maxn]; int lazy[maxn]; bool reserve[maxn],same[maxn]; int root,top1,top2; int max(int a,int b) { return a > b ? a : b; } int max(int a,int b,int c) { return max(max(a,b),c); } void swap(int &a,int &b) { int t = a;a = b;b = t; } void push_up(int x) { sz[x] = sz[ ch[x][0] ] + sz[ ch[x][1] ] + 1; sum[x] = val[x] + sum[ ch[x][0] ] + sum[ ch[x][1] ]; Maxl[x] = max(Maxl[ ch[x][0] ],sum[ ch[x][0] ] + val[x] + max(0,Maxl[ ch[x][1] ])); Maxr[x] = max(Maxr[ ch[x][1] ],sum[ ch[x][1] ] + val[x] + max(0,Maxr[ ch[x][0] ])); Max[x] = max(Max[ ch[x][0] ],Max[ ch[x][1] ],val[x]); Max[x] = max(Max[x],max(Maxr[ ch[x][0] ],Maxl[ ch[x][1] ]) + val[x]); Max[x] = max(Max[x],Maxr[ ch[x][0] ] + val[x] + Maxl[ ch[x][1] ]); }void deal1(int x,int tmp){same[x] = true,lazy[x] = tmp;sum[x] = tmp * sz[x];Max[x] = Maxl[x] = Maxr[x] = max(sum[x],tmp);} void deal2(int x) { reserve[x] = !reserve[x]; swap(Maxl[x],Maxr[x]); } void push_down(int x) { if(same[x]) {val[x] = lazy[x];if(ch[x][0])deal1(ch[x][0],lazy[x]);if(ch[x][1])deal1(ch[x][1],lazy[x]);same[x] = reserve[x] = false; } if(reserve[x]) { swap(ch[x][0],ch[x][1]); swap(Maxl[x],Maxr[x]); if(ch[x][0])deal2(ch[x][0]); if(ch[x][1])deal2(ch[x][1]); reserve[x] = false; } } void Rotate(int x,int f) { int y = pre[x]; push_down(y);push_down(x); ch[y][!f] = ch[x][f]; pre[ ch[x][f] ] = y; pre[x] = pre[y]; if(pre[x])ch[ pre[y] ][ ch[pre[y]][1] == y ] = x; ch[x][f] = y; pre[y] = x; push_up(y); } void Splay(int x,int goal) { push_down(x); while(pre[x] != goal) { if(pre[pre[x]] == goal)Rotate(x, ch[pre[x]][0] == x); else { int y = pre[x],z = pre[y]; int f = (ch[z][0] == y); if(ch[y][f] == x)Rotate(x,!f),Rotate(x,f); else Rotate(y,f),Rotate(x,f); } } push_up(x); if(goal == 0)root = x; } void RotateTo(int k,int goal) { int x = root; push_down(x); while(sz[ ch[x][0] ] != k) { if(k < sz[ ch[x][0] ])x = ch[x][0]; else { k -= (sz[ ch[x][0] ] + 1); x = ch[x][1]; } push_down(x); } Splay(x,goal); } void Newnode(int &x,int c) { if(top2)x = ss[--top2]; else x = ++top1; ch[x][0] = ch[x][1] = pre[x] = 0; sz[x] = 1; lazy[x] = 0; reserve[x] = same[x] = false; val[x] = sum[x] = c; Maxl[x] = Maxr[x] = Max[x] = c; } void makeTree(int &x,int l,int r,int f,int *p) { if(l > r)return; int m = (l + r) >> 1; Newnode(x,p[m]); makeTree(ch[x][0],l , m - 1,x,p); makeTree(ch[x][1],m + 1 , r,x,p); pre[x] = f; push_up(x); } void erase(int x) { int father = pre[x]; int head = 0,tail = 0; for(que[tail++] = x;head < tail;head ++) { ss[top2++] = que[head]; if(ch[ que[head] ][0])que[tail++] = ch[ que[head] ][0]; if(ch[ que[head] ][1])que[tail++] = ch[ que[head] ][1]; } ch[ father ][ ch[father][1] == x ] = 0; push_up(father); } void init(int n) {memset(Max,~0x3f,sizeof(Max)); ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0; root = top1 = top2 = 0; Newnode(root,-inf); Newnode(ch[root][1],-inf); pre[ch[root][1]] = root; sz[root] = 2; for(int i = 1;i <= n;i++)scanf("%d",&num[i]); makeTree(keyTree,1,n,ch[root][1],num); push_up(ch[root][1]); push_up(root); } void ins(int pos,int tot,int *tmp) { RotateTo(pos,0);RotateTo(pos + 1,root); makeTree(keyTree,1,tot,ch[root][1],tmp); Splay(keyTree,0); } void update(int pos,int tot,int c) { RotateTo(pos - 1,0);RotateTo(pos + tot,root);deal1(keyTree,c); Splay(keyTree,0); } void del(int pos,int tot) { RotateTo(pos - 1,0);RotateTo(pos + tot,root); erase(keyTree); Splay(ch[root][1],0); } void res(int pos,int tot) { RotateTo(pos - 1,0);RotateTo(pos + tot,root); reserve[ keyTree ] = !reserve[ keyTree ]; Splay(keyTree,0); } int getsum(int pos,int tot) { RotateTo(pos - 1,0);RotateTo(pos + tot,root); return sum[ keyTree ]; } int query(){return Max[root];}}Spt;int n,m;int tmp[maxn];void init(){ freopen("bzoj1500.in","r",stdin); freopen("bzoj1500.out","w",stdout);} void readdata(){ scanf("%d%d",&n,&m); Spt.init(n); for(int i = 1;i <= m;i++) { char op[10]; int pos,tot; scanf("%s",op); if(!strcmp(op,"MAX-SUM"))printf("%d\n",Spt.query()); else { scanf("%d%d",&pos,&tot); if(!strcmp(op,"INSERT")) { for(int j = 1;j <= tot;j++)scanf("%d",&tmp[j]); Spt.ins(pos,tot,tmp); } if(!strcmp(op,"DELETE"))Spt.del(pos,tot); if(!strcmp(op,"MAKE-SAME")) { int c; scanf("%d",&c); Spt.update(pos,tot,c); } if(!strcmp(op,"REVERSE"))Spt.res(pos,tot); if(!strcmp(op,"GET-SUM"))printf("%d\n",Spt.getsum(pos,tot)); } }} int main(){ init(); readdata(); return 0;}
- 【NOI2005】【splay】维护数列
- 【SPLAY】NOI2005 维护数列
- noi2005维护数列 splay
- splay BZOJ1500 NOI2005 维护数列
- 【jzoj2413】【NOI2005】【维护数列】【splay】
- bsoj 2246 【NOI2005】维护数列(splay解法)
- NOI2005维护数列 伸展树splay
- CODEVS-1758-维护数列-NOI2005-splay
- BZOJ 1500([NOI2005]维修数列-Splay的数列维护)
- noi2005 维护序列。 splay
- NOI2005 维修数列(splay)
- [NOI2005]维修数列 (Splay)
- [Splay] NOI2005 维修数列
- NOI2005 维修数列 Splay
- 【noi2005】维护数列
- [NOI2005] 维护数列 sequence
- 数列维护 NOI2005
- 【noi2005】维护数列
- HTTP HTTPS WebService
- 1012. Joseph
- Java程序设计—孙鑫java无难事教程Lesson1《java技术与应用》
- 浅谈11g数据库flashback 特性
- union all和union的区别
- 【NOI2005】【splay】维护数列
- 分页及三级联动项目
- uva 11520 - Fill the Square
- java程序设计--孙鑫java无难事Lesson2《位运算及面向对象程序设计》
- c3p0,dbcp和proxool
- java程序设计--孙鑫java无难事Lesson3《包、类和方法说明符、垃圾回收、接口》
- http jsp 字符集问题
- {C++小知识}C++拷贝构造函数(深拷贝,浅拷贝)
- 黑马程序员---String类及StringBuffer