题意:
给出一个长度为n的数列和m个操作;
对每个5,6操作输出一个答案;
被bz吃掉的数据范围:
你可以认为在任何时刻,数列中至少有1个数;
输入数据一定是正确的,即指定位置的数在数列中一定存在;
50%的数据中,任何时刻数列中最多含有30 000个数;
100%的数据中,任何时刻数列中最多含有500 000个数;
100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内;
100%的数据中,M ≤20 000,插入的数字总数不超过4 000 000个。
题解:
写完这道题,我觉得人生无憾了;
首先分析一下题目;
1,2操作涉及到区间的加入删除,显然是一个splay;
3,4操作是区间的更改,对这样的大数据范围要维护延时标记;
5,6操作是输出,没啥说的;
再看数据范围,数列长度不超过500 000,插入个数不超过4 000 000;
我个蒟蒻居然直接开大数组就搞了,并没有考虑内存回收的问题;
然后WA了半天并且并不能对拍出错;
所以数组开小为什么不是RE啊!!
我开大了5倍内存在cena上A了。。。
↑所以内存要回收↑
为了方便一点去对两边取区间,我在两端加了两个无用结点;
维护6询问就是维护左面的最大值右面的最大值和中间的最大值,分别用lm,rm,ma表示咯;
但是因为两个无用结点,让问题变得有些复杂;
如果无用结点值为0,那么当整个区间都为负数时答案为0,而题目要求必须取一个最大的负数;
如果无用结点值为负无穷,在维护sum的时候可能会出问题,并且int内负无穷加着加着就变成正无穷了(笑);
所以我记录了一个ign的标记,赋给了两个无用结点和0结点;
就是在求最大值的时候无视他们的值;
然后说说标记的问题;
3操作小心将区间维护为0,如果仅用判断标记是否为0就会挂在这;
4操作注意一下Pushdown的时候当前结点的左右子树已经交换了,应当交换的是子树的左右子树;
交换时直接交换左右子树的标号和lm与rm即可;
别的没什么说的了,splay实现我开了结构体,不过无所谓啦;
实际上开结构体除了回收内存直接memset方便一点以外都是比较麻烦的;
附赠对拍用数据生成器一个(下面);
代码:
#include<stdio.h> #include<string.h> #include<algorithm> #define N 510000 #define lson tr[tr[x].ch[0]] #define rson tr[tr[x].ch[1]] #define which(x) (tr[tr[x].fa].ch[1]==x) using namespace std; struct splay_tree { int val,ch[2],fa,size,sum,lm,rm,ma,cov; bool flag1,flag2,ign; }tr[N]; char str[100]; int root,tot,st[N],top; void Pushup(int x) { tr[x].sum=lson.sum+rson.sum+tr[x].val; tr[x].size=lson.size+rson.size+1; tr[x].lm=max(lson.lm,lson.sum+tr[x].val+max(rson.lm,0)); tr[x].rm=max(rson.rm,tr[x].val+rson.sum+max(lson.rm,0)); tr[x].ma=max(max(lson.rm,0)+(tr[x].ign?-0x3f3f3f3f:tr[x].val)+max(rson.lm,0),max(lson.ma,rson.ma)); } void Pushdown(int x) { if(tr[x].flag2) { if(tr[x].ch[0]) { lson.flag2=1; lson.val=lson.cov=tr[x].cov; lson.sum=lson.size*tr[x].cov; lson.lm=lson.rm=lson.ma=max(lson.cov,lson.sum); } if(tr[x].ch[1]) { rson.flag2=1; rson.val=rson.cov=tr[x].cov; rson.sum=rson.size*tr[x].cov; rson.lm=rson.rm=rson.ma=max(rson.cov,rson.sum); } } else if(tr[x].flag1) { lson.flag1^=1,rson.flag1^=1; swap(lson.ch[0],lson.ch[1]); swap(lson.lm,lson.rm); swap(rson.ch[0],rson.ch[1]); swap(rson.lm,rson.rm); } tr[x].flag1=tr[x].flag2=tr[x].cov=0; } int Build(int l,int r,int f) { if(l>r) return 0; int mid=(l+r)>>1,x; if(top) x=st[top--]; else x=++tot; tr[x].fa=f; tr[x].ch[0]=Build(l,mid-1,x); scanf("%d",&tr[x].val); tr[x].ch[1]=Build(mid+1,r,x); if(l==r) { tr[x].size=1; tr[x].sum=tr[x].val; tr[x].lm=tr[x].rm=tr[x].ma=tr[x].val; } else Pushup(x); return x; } void Rotate(int x) { int f=tr[x].fa; bool k=which(x); tr[f].ch[k]=tr[x].ch[!k]; tr[tr[x].ch[!k]].fa=f; tr[x].ch[!k]=f; tr[tr[f].fa].ch[which(f)]=x; tr[x].fa=tr[f].fa; tr[f].fa=x; Pushup(f); Pushup(x); } void Splay(int x,int g) { if(!x) return ; while(tr[x].fa!=g) { int f=tr[x].fa; if(tr[f].fa==g) { Rotate(x); continue; } if(which(f)^which(x)) Rotate(x); else Rotate(f); Rotate(x); } if(!g) root=x; } int Rank(int x,int k) { if(x==0||k==0) return 0; Pushdown(x); if(k<=lson.size) return Rank(tr[x].ch[0],k); else if(k==lson.size+1) return x; else return Rank(tr[x].ch[1],k-lson.size-1); } void Init(int n) { int x; x=Rank(root,1); Splay(x,0); tr[x].ch[0]=++tot; tr[tot].ign=tr[tot].size=1; tr[tot].fa=x; tr[tot].lm=tr[tot].rm=tr[tot].ma=-0x3f3f3f3f; Pushup(x); x=Rank(root,1+n); Splay(x,0); tr[x].ch[1]=++tot; tr[tot].ign=tr[tot].size=1; tr[tot].fa=x; tr[tot].lm=tr[tot].rm=tr[tot].ma=-0x3f3f3f3f; Pushup(x); } void Getback(int x) { if(!x) return ; st[++top]=x; Getback(tr[x].ch[0]); Getback(tr[x].ch[1]); memset(&tr[x],0,sizeof(splay_tree)); } void Insert() { int p,n,x,y; scanf("%d%d",&p,&n); p++; x=Rank(root,p); Splay(x,0); y=Rank(root,p+1); Splay(y,x); tr[y].ch[0]=Build(1,n,y); Pushup(y); Pushup(x); } void Delete() { int p,n,x,y; scanf("%d%d",&p,&n); p++; x=Rank(root,p-1); Splay(x,0); y=Rank(root,p+n); Splay(y,x); Getback(tr[y].ch[0]); tr[y].ch[0]=0; Pushup(y); Pushup(x); } void Update() { int p,n,v,x,y,t; scanf("%d%d%d",&p,&n,&v); p++; x=Rank(root,p-1); Splay(x,0); y=Rank(root,p+n); Splay(y,x); t=tr[y].ch[0]; tr[t].flag2=1; tr[t].val=tr[t].cov=v; tr[t].sum=tr[t].size*v; tr[t].lm=tr[t].rm=tr[t].ma=max(v,tr[t].sum); Pushup(y); Pushup(x); } void Reverse() { int p,n,x,y,t; scanf("%d%d",&p,&n); p++; x=Rank(root,p-1); Splay(x,0); y=Rank(root,p+n); Splay(y,x); t=tr[y].ch[0]; tr[t].flag1^=1; swap(tr[t].ch[0],tr[t].ch[1]); swap(tr[t].lm,tr[t].rm); Pushup(y); Pushup(x); } void Getsum() { int p,n,x,y,t; scanf("%d%d",&p,&n); p++; x=Rank(root,p-1); Splay(x,0); y=Rank(root,p+n); Splay(y,x); t=tr[y].ch[0]; printf("%d\n",tr[t].sum); Pushup(y); Pushup(x); } void Getmax() { printf("%d\n",tr[root].ma); } int main() { int n,m,i,j,k,x,y; scanf("%d%d",&n,&m); tr[0].ign=1; tr[0].lm=tr[0].rm=tr[0].ma=-0x3f3f3f3f; root=Build(1,n,0); Init(n); for(i=1;i<=m;i++) { scanf("%s",str); switch(str[2]) { case 'S':Insert(); break; case 'L':Delete(); break; case 'K':Update(); break; case 'V':Reverse(); break; case 'T':Getsum(); break; case 'X':Getmax(); } } return 0; }
#include<stdio.h> #include<string.h> #include<algorithm> #define Random rand()%2000-1000 using namespace std; typedef long long ll; int main() { srand(time(NULL)); int n=300,m=10; int i,j,k,x,y; printf("%d %d\n",n,m); for(i=1;i<=n;i++) printf("%d ",Random); puts(""); for(i=1;i<=m;i++) { k=rand()%6; if(!n) return 0; x=rand()%n+1; y=rand()%(n-x+1)+1; switch(k) { case 0: puts("INSERT"); printf("%d %d ",x,y); for(j=1;j<=y;j++) printf("%d ",Random); puts(""); n+=y; break; case 1: puts("DELETE"); printf("%d %d\n",x,y); n-=y; break; case 2: puts("MAKE-SAME"); printf("%d %d %d\n",x,y,Random); break; case 3: puts("REVERSE"); printf("%d %d\n",x,y); break; case 4: puts("GET-SUM"); printf("%d %d\n",x,y); break; case 5: puts("MAX-SUM"); break; } } return 0; }
原文地址:http://blog.csdn.net/ww140142/article/details/46669127