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
#include
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;
}