Time Limit:20000MS Memory Limit:200000K Description
Input
Output
Sample Input
Sample Output
Hint Source xinyue |
题目:http://mail.bashu.cn:8080/bs_oj/showproblem?problem_id=2246
题意:给你一个数列,每次可能插入一些数,删除一些数,翻转一个区间,询问一个区间的和,还有询问最大的和区间,将一个区间置为相同的一个值。。。
分析:赋值,删除,插入,还有区间和,都比较简单,而翻转和求最大区间和,这个比较麻烦,用到线段树的延迟标记,翻转的话,和赋值差不多,加一个翻转标记,每次下传时,对调两个子节点就行,而最大区间和值,这个需要维护三个值域,一个区间最左开始的最大和,一个区间最右开始的最大和,还有这个区间的最大和。。。
具体自己琢磨下,会更清晰。。。
我的模板貌似慢死了,不加读入优化直接TLE,别人的照样A啊。。。T_T
我得看看他们的代码 ,优化优化^_^
代码:
#include<cstdio> #include<iostream> using namespace std; const int mm=555555; int a[mm]; int getint() { char ch; int flag = 0, tmp = 0; for (ch = getchar(); ch < 48 || ch > 57; ch = getchar()) if (ch == int('-')) break; if (ch == int('-')) flag = 1; else tmp = int(ch) - 48; for (ch = getchar(); 48 <= ch && ch <= 57; ch = getchar()) tmp = tmp * 10 + int(ch) - 48; return (flag) ? -tmp : tmp; } struct SplayTree { int son[mm][2],far[mm],num[mm],val[mm],q[mm]; int sum[mm],lms[mm],rms[mm],ms[mm],dly[mm],w[mm],turn[mm]; int rt,size,top; void Link(int x,int y,int c) { far[x]=y,son[y][c]=x; } void Rotate(int x,int c) { int y=far[x]; PushDown(y); PushDown(x); Link(x,far[y],son[far[y]][1]==y); Link(son[x][!c],y,c); Link(y,x,!c); PushUp(y); } void Splay(int x,int g) { for(PushDown(x); far[x]!=g;) { int y=far[x],cx=son[y][1]==x,cy=son[far[y]][1]==y; if(far[y]==g)Rotate(x,cx); else { if(cx==cy)Rotate(y,cy); else Rotate(x,cx); Rotate(x,cy); } } PushUp(x); if(!g)rt=x; } int Select(int k,int g) { int x=rt; PushDown(x); while(num[son[x][0]]!=k) { if(num[son[x][0]]>k)x=son[x][0]; else k-=num[son[x][0]]+1,x=son[x][1]; PushDown(x); } Splay(x,g); return x; } void MemPool(int x) { if(!x)return; q[top++]=x; MemPool(son[x][0]); MemPool(son[x][1]); } void NewNode(int y,int &x,int a) { x=top?q[--top]:++size; far[x]=y,val[x]=a,num[x]=1; sum[x]=lms[x]=rms[x]=ms[x]=0; dly[x]=turn[x]=son[x][0]=son[x][1]=0; } void Make(int l,int r,int &x,int y) { if(l>r)return; int m=(l+r)>>1; NewNode(y,x,a[m]); Make(l,m-1,son[x][0],x); Make(m+1,r,son[x][1],x); PushUp(x); } void Build(int x,int n) { for(int i=1; i<=n; ++i) a[i]=getint(); Make(1,n,son[x][0],x); Splay(x,0); } void Prepare(int n) { ms[0]=lms[0]=rms[0]=-1e9,sum[0]=0; NewNode(top=size=0,rt,0); NewNode(rt,son[1][1],0); num[rt]=2; Build(2,n); } int Interval(int l,int r) { Select(l,0); return Select(r,rt); } void Insert(int p,int n) { Build(Interval(p,p+1),n); } void Delete(int p,int n) { int x=Interval(p-1,p+n); MemPool(son[x][0]); son[x][0]=0; Splay(x,0); } void Same(int p,int n,int a) { int x=Interval(p-1,p+n); Change(son[x][0],a); Splay(x,0); } void Reverse(int p,int n) { int x=Interval(p-1,p+n); Turn(son[x][0]); Splay(x,0); } int GetSum(int p,int n) { int x=Interval(p-1,p+n); return sum[son[x][0]]; } int MaxSum() { return ms[rt]; } void Change(int x,int a) { if(!x)return; dly[x]=1,w[x]=a; sum[x]=a*num[x]; ms[x]=lms[x]=rms[x]=max(sum[x],a); } void Turn(int x) { turn[x]^=1; swap(lms[x],rms[x]); } void PushDown(int x) { if(dly[x]) { val[x]=w[x]; Change(son[x][0],w[x]); Change(son[x][1],w[x]); turn[x]=dly[x]=0; } else if(turn[x]) { swap(son[x][0],son[x][1]); Turn(son[x][0]); Turn(son[x][1]); turn[x]=0; } } void PushUp(int x) { int a=son[x][0],b=son[x][1]; num[x]=1+num[a]+num[b]; sum[x]=val[x]+sum[a]+sum[b]; ms[x]=max(ms[a],ms[b]); lms[x]=lms[a],rms[x]=rms[b]; if(x>2) { ms[x]=max(ms[x],val[x]+max(0,rms[a])+max(0,lms[b])); lms[x]=max(lms[x],sum[a]+val[x]+max(0,lms[b])); rms[x]=max(rms[x],max(0,rms[a])+val[x]+sum[b]); } } } spt; int i,j,k,n,m; char op[22]; int main() { n=getint(),m=getint(); spt.Prepare(n); while(m--) { scanf("%s",op); if(op[0]!='M')i=getint(),j=getint();; if(op[0]=='I')spt.Insert(i,j); if(op[0]=='D')spt.Delete(i,j); if(op[0]=='M'&&op[2]=='K') { i=getint(),j=getint(),k=getint(); spt.Same(i,j,k); } if(op[0]=='R')spt.Reverse(i,j); if(op[0]=='G')printf("%d\n",spt.GetSum(i,j)); if(op[0]=='M'&&op[2]=='X')printf("%d\n",spt.MaxSum()); } return 0; }