题目:bzoj1500
题意:
Description
Input
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
Output
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
Sample Input
9 8
2 -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
2 -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
-1
10
1
10
10
1
10
HINT
Source
HOME Back
分析:Splay~
各种bug。。。
总算A了!
求最大连续和的那部分,参考之前写的线段树区间合并的方法我是链接。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
//const int MI = ~0u>>1; //这样写会爆!!! waaaaaaaaaaaa
const int MI = 1E9;
inline int _3max(int a,int b,int c)
{
int ret=(a>b?a:b);
return ret>c?ret:c;
}
#define lson son[rt][0]
#define rson son[rt][1]
#define getPos son[son[root][1]][0]
const int maxn = 555555;
int son[maxn][2],fa[maxn],sz[maxn],val[maxn];
int setv[maxn]; //延迟标记,区间赋值
int flip[maxn]; //延迟标记,区间反转
int sum[maxn]; //区间和
int lsum[maxn],maxsum[maxn],rsum[maxn]; //连续和相关
int root,cnt;
int pool[maxn*2],tot; //内存池,内存池容量
int a[maxn],n,q;
inline int newnode(int f,int v)
{
int r=-1;
if(tot) r=pool[--tot];
else r=++cnt;
son[r][0]=son[r][1]=0;
fa[r]=f;sz[r]=1;val[r]=v;
flip[r]=setv[r]=0;
sum[r]=lsum[r]=rsum[r]=maxsum[r]=v; //开始手贱 写成sum[r]=-v waaaa...
return r;
}
void Recycle(int rt)
{
if(!rt) return;
pool[tot++]=rt;
Recycle(lson);
Recycle(rson);
}
inline void update_same(int rt,int v)
{
if(!rt) return ;
val[rt]=v;
sum[rt]=sz[rt]*v;
maxsum[rt]=lsum[rt]=rsum[rt]=max(v,sz[rt]*v); //忘记更新maxsum waaaaa...
setv[rt]=1;
}
inline void update_rev(int rt)
{
if(!rt) return ;
swap(lson,rson);
swap(lsum[rt],rsum[rt]);
flip[rt]^=1;
}
void pushdown(int rt)
{
if(setv[rt])
{
update_same(lson,val[rt]);
update_same(rson,val[rt]);
setv[rt]=0;
}
if(flip[rt])
{
update_rev(lson);
update_rev(rson);
flip[rt]=0;
}
}
void pushup(int rt)
{
sz[rt]=sz[lson]+sz[rson]+1;
sum[rt]=sum[lson]+sum[rson]+val[rt];
lsum[rt]=_3max(lsum[lson],sum[lson]+val[rt],sum[lson]+val[rt]+lsum[rson]);
rsum[rt]=_3max(rsum[rson],sum[rson]+val[rt],sum[rson]+val[rt]+rsum[lson]);
maxsum[rt]=max(_3max(maxsum[lson],maxsum[rson],val[rt]),_3max(rsum[lson]+val[rt],val[rt]+lsum[rson],rsum[lson]+val[rt]+lsum[rson]));
}
void buildSplay(int l,int r,int &rt,int fa)
{
if(l>r) return ;
int mid=l+r>>1;
rt=newnode(fa,a[mid]);
buildSplay(l,mid-1,lson,rt);
buildSplay(mid+1,r,rson,rt);
pushup(rt);
}
void debug(int rt)
{
if(rt)
{
pushdown(rt);
debug(lson);
printf("节点:%d | lson:%d rson:%d val:[%d] \n",rt,lson,rson,val[rt]);
debug(rson);
pushup(rt);
}
}
void Rotate(int r,int kind)
{
int y=fa[r];
pushdown(y);
pushdown(r);
son[y][kind^1]=son[r][kind];
fa[son[r][kind]] = y;
if(fa[y]!=0)
son[fa[y]][son[fa[y]][1]==y] = r;
fa[r]=fa[y];
son[r][kind]=y;
fa[y]=r;
pushup(y);
}
void Splay(int r,int goal)
{
pushdown(r);
while(fa[r]!=goal)
{
if(goal==fa[fa[r]])
Rotate(r,son[fa[r]][0]==r);
else
{
int y=fa[r];
int kind=son[fa[y]][0]==y;
if(son[y][kind]==r)
{
Rotate(r,kind^1);
Rotate(r,kind);
}
else
{
Rotate(y,kind);
Rotate(r,kind);
}
}
}
if(0==goal)
root=r;
pushup(r);
}
void RotateTo(int k,int goal) //将代表位置k的节点移到goal下面
{
int rt=root;
while(rt)
{
pushdown(rt);
if(sz[lson]+1==k) break;
if(k>sz[lson]+1)
{
k-=(sz[lson]+1);
rt=rson;
}
else rt=lson;
}
Splay(rt,goal);
}
void Insert(int posi,int num)
{
for(int i=1;i<=num;i++)
scanf("%d",&a[i]);
RotateTo(posi+1,0);
RotateTo(posi+2,root);
buildSplay(1,num,getPos,son[root][1]);
pushup(son[root][1]);
pushup(root);
}
void Delete(int posi,int num)
{
int L=posi,R=posi+num-1;
RotateTo(L,0);
RotateTo(R+2,root);
Recycle(getPos);
fa[getPos]=0;
getPos=0;
pushup(son[root][1]);
pushup(root);
}
void Modify(int posi,int num,int c)
{
int L=posi,R=posi+num-1;
RotateTo(L,0);
RotateTo(R+2,root);
update_same(getPos,c);
pushup(son[root][1]);
pushup(root);
}
void Reverse(int posi,int num)
{
int L=posi,R=posi+num-1;
RotateTo(L,0);
RotateTo(R+2,root);
update_rev(getPos);
pushup(son[root][1]);
pushup(root);
}
void getSum(int posi,int num)
{
int L=posi,R=posi+num-1;
RotateTo(L,0);
RotateTo(R+2,root);
printf("%d\n",getPos?sum[getPos]:0);
}
void getMaxSum()
{
RotateTo(1,0);
RotateTo(sz[root],root);
printf("%d\n",getPos?maxsum[getPos]:0);
}
void Init()
{
tot=0; //回收的内存为空
cnt=root=0;
son[root][0]=son[root][1]=fa[root]=sz[root]=setv[root]=flip[root]=sum[root]=0;
lsum[root]=rsum[root]=maxsum[root]=val[root]=-MI;
root=newnode(0,-MI);
son[root][1]=newnode(root,-MI);
pushup(root);
buildSplay(1,n,getPos,son[root][1]);
pushup(son[root][1]);
pushup(root);
}
int main()
{
while(scanf("%d%d",&n,&q)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
Init();
char op[10];
int posi,num,c;
while(q--)
{
scanf("%s",op);
switch(op[0])
{
case 'I':scanf("%d%d",&posi,&num);Insert(posi,num);break;
case 'D':scanf("%d%d",&posi,&num);Delete(posi,num);break;
case 'R':scanf("%d%d",&posi,&num);Reverse(posi,num);break;
case 'G':scanf("%d%d",&posi,&num);getSum(posi,num);break;
case 'M':
if(op[2]=='K') {scanf("%d%d%d",&posi,&num,&c);Modify(posi,num,c);}
else getMaxSum();
}
// debug(root);cout<<'\n';
}
}
return 0;
}