【POJ2750】最大连续和
Description
给出一个含有N个结点的环,编号分别为1..N,环上的点带有权值(可正可负),现要动态的修改某个点的权值,求每次修改后环上的最大连续和,但不能是整个序列的和。
Input
第一行为一个整数N(4<=N<=100000);
第二行为N个用空格分开的整数;
第三行为一个整数M(4<=M<=100000),表示修改的次数(绝对值小于等于1000);
接下来M行,每行两个整数A和B(-1000<=B<=1000),表示将序列中的第A个数的值,修改为B。
第二行为N个用空格分开的整数;
第三行为一个整数M(4<=M<=100000),表示修改的次数(绝对值小于等于1000);
接下来M行,每行两个整数A和B(-1000<=B<=1000),表示将序列中的第A个数的值,修改为B。
Output
对于每个修改,输出修改后环上的最大连续和。
Sample Input
5
3 -2 1 2 -5
4
2 -2
5 -5
2 -4
5 -1
Sample Output
4
4
3
5
Solution
给定一个环,要求维护这个环上的最大连续和,只有修改操作。
我们首先分析在没有修改的情况下的最大连续和。一个环上的最大连续和就是1~n序列的最大连续和与总和减去1~n序列的最小连续和中的最大值。对于得出的答案恰好等于总和的情况,我们将总和减去最小连续和就是答案了。
CODE
非常尴尬的写了Splay。。。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
inline int read(){
char c;int rec=0,f=1;
while((c=getchar())<'0'||c>'9')if(c=='-')f=-1;
while(c>='0'&&c<='9')rec=rec*10+c-'0',c=getchar();
return rec*f;
}
int root,cnt,c[100005];
int n,m,V;
struct Splay_Tree{
int F,s[2],size,val;
int sum,maxx,minn,pmax[2],pmin[2];
inline void NewNode(int fa,int x){
F=fa;val=sum=maxx=minn=pmax[0]=pmax[1]=pmin[0]=pmin[1]=x;size=1;s[0]=s[1]=0;return ;
}
}tree[100005];
inline void PMAX(int v,int f){
tree[v].pmax[f]=max(tree[tree[v].s[f]].pmax[f],
tree[tree[v].s[f]].sum+tree[v].val+max(0,tree[tree[v].s[!f]].pmax[f]));
}
inline void PMIN(int v,int f){
tree[v].pmin[f]=min(tree[tree[v].s[f]].pmin[f],
tree[tree[v].s[f]].sum+tree[v].val+min(0,tree[tree[v].s[!f]].pmin[f]));
}
inline void Pushup(int v){
tree[v].size=tree[tree[v].s[0]].size+1+tree[tree[v].s[1]].size;
tree[v].sum=tree[tree[v].s[0]].sum+tree[v].val+tree[tree[v].s[1]].sum;
tree[v].maxx=max(max(tree[tree[v].s[0]].maxx,tree[tree[v].s[1]].maxx),
max(0,tree[tree[v].s[0]].pmax[1])+tree[v].val+max(0,tree[tree[v].s[1]].pmax[0]));
PMAX(v,0);PMAX(v,1);
tree[v].minn=min(min(tree[tree[v].s[0]].minn,tree[tree[v].s[1]].minn),
min(0,tree[tree[v].s[0]].pmin[1])+tree[v].val+min(0,tree[tree[v].s[1]].pmin[0]));
PMIN(v,0);PMIN(v,1);
return ;
}
inline void Rotate(int v){
int p=tree[v].F,g=tree[p].F;
int f1=(v==tree[p].s[1]),f2=(p==tree[g].s[1]),S=tree[v].s[!f1];
tree[g].s[f2]=v;tree[v].F=g;
tree[p].s[f1]=S;tree[S].F=p;
tree[v].s[!f1]=p;tree[p].F=v;
Pushup(p);return ;
}
inline void Splay(int v,int goal){
while(tree[v].F!=goal){
int p=tree[v].F,g=tree[p].F;
if(g!=goal)(v==tree[p].s[1])^(p==tree[g].s[1])?Rotate(v):Rotate(p);
Rotate(v);
}Pushup(v);if(!goal)root=v;
return ;
}
inline int Build(int L,int R,int fa){
if(L>R)return 0;
int mid=(L+R)>>1,p=++cnt;
tree[p].NewNode(fa,c[mid]);
tree[p].s[0]=Build(L,mid-1,p);
tree[p].s[1]=Build(mid+1,R,p);
Pushup(p);return p;
}
inline void Kth(int k){
int v=root;
while(tree[tree[v].s[0]].size+1!=k){
if(tree[tree[v].s[0]].size+1>k)v=tree[v].s[0];
else {k-=tree[tree[v].s[0]].size+1;v=tree[v].s[1];}
}V=v;return ;
}
inline void Pre(int x,int y){Kth(x);Splay(V,0);Kth(y);Splay(V,root);return ;}
inline void Change(int x,int y){Pre(x-1,x+1);tree[tree[V].s[0]].NewNode(V,y);Pushup(V);Pushup(root);return ;}
int main(){
n=read();
int i,x,y;
for(i=1;i<=n;i++)c[i]=read();
tree[++cnt].NewNode(0,0);
tree[++cnt].NewNode(1,0);
tree[1].s[1]=2;root=1;
tree[2].s[0]=Build(1,n,2);
m=read();
for(i=1;i<=m;i++){
x=read();y=read();x++;Change(x,y);
if(tree[root].maxx==tree[root].sum){cout<<tree[root].maxx-tree[root].minn<<'\n';}
else cout<<max(tree[root].maxx,tree[root].sum-tree[root].minn)<<'\n';
}
return 0;
}