【splay】BZOJ 1500: [NOI2005]维修数列
2015-12-29 15:20
381 查看
BZOJ 1500 维修数列
Description
Input
输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。第2行包含N个数字,描述初始时的数列。以下M行,每行一条命令,格式参见问题描述中的表格。Output
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。Sample Input
9 82 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM
Sample Output
-110
1
10
HINT
Solution
一道日狗的题目。。听说一小时之内A了这题才算掌握了splay?
机房的同学们都是一个晚上就A了
我这个大蒟蒻用了一天。。
最后还是某和我一起苦逼改题的同学的提醒我才A的。。
insert
和普通的insert没什么区别吧..
有两种添加方法:1.一条链添加下去,2.利用build函数(2方法好一些然而博主蒟蒻打的第一种)
记得要update!
delete
普通的delete..删除方法就是把L-1旋到根,R+1旋到根的右节点,然后把右节点的左子树删除即可
记得要update!
make_same
打tag
这里有个很重要的细节,不要把tag作为值下传.
tag要作为一个标记表示修改过了而不是一个值,值由当前节点的v来下传!
因为数据中有make_same 0的情况,如果使用tag存值的方法tag等于0时标记不会下传!
改了一个下午没改出来..最后还是在同学的提醒下才弄出来的。。
rev操作
和普通的rev一样,打标记下传.
get_sum
这个应该也是很简单的,update即可。
max_num
最难的一个操作
对于一个区间的最大子区间,我们在两种中取max:
1.左子树的最大区间/右子树的最大区间
2.右子树从左端开始向右的最大区间+左子树从右端开始向左的最大区间
而一段区间的两端开始的最大值(lx,rx)求法就是在以下两种中取max:
1.假如求lx,则是当前区间左子树区间的lx,rx反之
2.假如求lx,则是当前区间左子树区间的sum+右子树区间的lx,rx反之
注意rev操作要把左右各子树的lx和rx交换
其他:数组空间不够,需要使用队列回收删除节点重新利用!
打完以后整个人都不好了..
Code
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; #define maxn 500001 int root,size,que[maxn],head=1,tail=0,a[maxn+233],stack[maxn],top=0; bool ok[maxn]; inline int in() { int x=0,f=1;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')ch=getchar(),f=-1; while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar(); return x*f; } struct splay{ int size,ch[2],v,fa,sum,lx,rx,mx; bool rev,tag; }t[maxn],E; char s[233]; void pushdown(int k) { if(t[k].tag) { t[k].rev=0; if(t[k].ch[0])t[t[k].ch[0]].tag=t[k].tag,t[t[k].ch[0]].v=t[k].v,t[t[k].ch[0]].sum=t[k].v*t[t[k].ch[0]].size; if(t[k].ch[1])t[t[k].ch[1]].tag=t[k].tag,t[t[k].ch[1]].v=t[k].v,t[t[k].ch[1]].sum=t[k].v*t[t[k].ch[1]].size; if(t[k].v>=0) { if(t[k].ch[1])t[t[k].ch[1]].lx=t[t[k].ch[1]].rx=t[t[k].ch[1]].mx=t[t[k].ch[1]].sum; if(t[k].ch[0])t[t[k].ch[0]].lx=t[t[k].ch[0]].rx=t[t[k].ch[0]].mx=t[t[k].ch[0]].sum; } else { if(t[k].ch[1])t[t[k].ch[1]].lx=t[t[k].ch[1]].rx=0,t[t[k].ch[1]].mx=t[k].v; if(t[k].ch[0])t[t[k].ch[0]].lx=t[t[k].ch[0]].rx=0,t[t[k].ch[0]].mx=t[k].v; } t[k].tag=0; } if(t[k].rev) { t[k].rev=0; t[t[k].ch[0]].rev^=1; t[t[k].ch[1]].rev^=1; swap(t[t[k].ch[0]].ch[0],t[t[k].ch[0]].ch[1]); swap(t[t[k].ch[1]].ch[0],t[t[k].ch[1]].ch[1]); swap(t[t[k].ch[1]].lx,t[t[k].ch[1]].rx); swap(t[t[k].ch[0]].lx,t[t[k].ch[0]].rx); } } int find(int k,int x) { pushdown(k); if(t[t[k].ch[0]].size>=x)return find(t[k].ch[0],x); else if(t[t[k].ch[0]].size+1<x)return find(t[k].ch[1],x-1-t[t[k].ch[0]].size); else return k; } void update(int k) { int l=t[k].ch[0],r=t[k].ch[1]; t[k].size=t[t[k].ch[0]].size+t[t[k].ch[1]].size+1; t[k].sum=t[t[k].ch[0]].sum+t[t[k].ch[1]].sum+t[k].v; t[k].mx=max(t[l].mx,t[r].mx); t[k].mx=max(t[k].mx,t[l].rx+t[r].lx+t[k].v); t[k].lx=max(t[l].lx,t[l].sum+t[k].v+t[r].lx); t[k].rx=max(t[r].rx,t[r].sum+t[k].v+t[l].rx); } void axe(int x,int &k,int d) { int y,z; y=t[x].fa,z=t[y].fa; if(y==k)k=x; else {if(t[z].ch[0]==y)t[z].ch[0]=x; else t[z].ch[1]=y;} t[y].fa=x,t[x].fa=z,t[t[x].ch[d]].fa=y; t[y].ch[d^1]=t[x].ch[d];t[x].ch[d]=y; update(y);update(x); } void splay(int x,int &k) { int y,z; while(x!=k) { y=t[x].fa;z=t[y].fa; if(y!=k) { if(t[y].ch[0]==x&&t[z].ch[0]==y)axe(y,k,1); else if(t[y].ch[1]==x&&t[z].ch[1]==y)axe(y,k,0); else if(t[y].ch[1]==x&&t[z].ch[0]==y)axe(x,k,0); else if(t[y].ch[0]==x&&t[z].ch[1]==y)axe(x,k,1); } if(t[t[x].fa].ch[0]==x)axe(x,k,1); else axe(x,k,0); } } void build(int l,int r,int f) { if(r<l)return; if(l==r) { t[l].size=1; t[l].v=a[l];t[l].fa=f; if(r<f)t[f].ch[0]=r; else t[f].ch[1]=r; t[l].sum=t[l].v; if(a[l]>=0)t[l].lx=t[l].rx=t[l].mx=t[l].v; else t[l].lx=t[l].rx=0,t[l].mx=t[l].v; return; } int mid=(l+r)>>1; build(l,mid-1,mid);build(mid+1,r,mid); t[mid].v=a[mid]; t[mid].fa=f;update(mid); if(mid<f)t[f].ch[0]=mid; else t[f].ch[1]=mid; } inline int getnum() { int x=que[head++]; while(ok[x]){x=que[head++];if(head==maxn)head=0;} if(head==maxn)head=0; ok[x]=1; return x; } inline void inque(int k) { t[k]=E; ok[k]=0;tail++; if(tail==maxn)tail=0; que[tail]=k; } void del(int k) { if(t[k].ch[0])del(t[k].ch[0]); if(t[k].ch[1])del(t[k].ch[1]); inque(k); } int main() { int n,m,x,c,size=0; n=in();m=in();size=n+2; t[0].mx=a[1]=a[n+2]=-99999999; for(int i=2;i<=n+1;i++) a[i]=in(); build(1,n+2,0); root=(n+3)>>1; for(int i=n+3;i<maxn;i++)que[++tail]=i; for(int i=1;i<=m;i++) { memset(s,0,sizeof(s)); scanf("%s",s); if(s[0]=='I') { x=in(); top=in(); if(top==0)continue; int x1=find(root,x+1),x2=find(root,x+2); splay(x1,root);splay(x2,t[root].ch[1]); t[t[root].ch[1]].ch[0]=getnum(); int now=t[t[root].ch[1]].ch[0]; t[now].size=top; t[now].fa=t[root].ch[1]; t[now].v=in(); for(int j=1;j<top;j++) { t[now].ch[1]=getnum(); t[t[now].ch[1]].fa=now; now=t[now].ch[1]; t[now].size=top-j; t[now].v=in(); } update(now); while(now!=root) { now=t[now].fa; update(now); } //size+=top; //printf("size:%d\n",size); } else if(s[0]=='D') { x=in(); top=in(); int x1=find(root,x),x2=find(root,x+top+1); splay(x1,root);splay(x2,t[root].ch[1]); del(t[x2].ch[0]); t[x2].ch[0]=0; update(x2); update(x1); //size-=top; //printf("size:%d\n",size); } else if(s[0]=='M') { if(s[2]=='K') { x=in();top=in();c=in(); int x1=find(root,x),x2=find(root,x+top+1); splay(x1,root),splay(x2,t[root].ch[1]); t[t[x2].ch[0]].tag=1,t[t[x2].ch[0]].v=c; t[t[x2].ch[0]].sum=t[t[x2].ch[0]].size*c; int xx=t[x2].ch[0]; if(c>=0)t[xx].mx=t[xx].lx=t[xx].rx=t[xx].sum; else t[xx].lx=t[xx].rx=0,t[xx].mx=t[xx].v; update(x2); update(x1); } else { printf("%d\n",t[root].mx); } } else if(s[0]=='R') { x=in();top=in(); int x1=find(root,x),x2=find(root,x+top+1); splay(x1,root),splay(x2,t[root].ch[1]); t[t[x2].ch[0]].rev^=1; swap(t[t[x2].ch[0]].ch[0],t[t[x2].ch[0]].ch[1]); swap(t[t[x2].ch[0]].lx,t[t[x2].ch[0]].rx); update(x2); update(x1); } else if(s[0]=='G') { x=in();top=in(); int x1=find(root,x); int x2=find(root,x+top+1); splay(x1,root),splay(x2,t[root].ch[1]); printf("%d\n",t[t[x2].ch[0]].sum); } } }
相关文章推荐
- (转)R语言 SVM支持向量机在 R 语言中的实现和使用
- Objective-C基础笔记(8)Foundation经常使用类NSString
- 在WordPress中实现发送http请求的相关函数解析
- php中__autoload和spl_autoload_register的用法
- lamp安装
- 【AngularJs】---angular-chart.js 图表报表
- 书单
- Android屏幕截图
- Python逐行读取文件内容
- 程序员 10Tips
- 你是码农还是优秀程序员?
- jQuery源码分析8--小结1
- IOS 图片拉伸技巧
- HBase经常使用操作之namespace
- 在阿里云的CentOS环境中安装django
- 浅谈压缩感知(十六):感知矩阵之RIP
- zabbix-agent监控windows
- Oracle排名函数(Rank)实例详解
- ibm aix I/O ERROR DETECTED BY LVM
- iOS 简单九宫格