pot
Description
这个假期,小h在自家院子里种了许多花,它们围成了一个圈,从1…n编号(n<=100000),小h 对每盆花都有一个喜好值xi,(-1000<=xi<=1000),小h现在觉得这样一成不变很枯燥,于是他做了m(m<=100000)个改动,每次把第ki盘花改成喜好值为di的花,然后小h要你告诉他,在这个花圈中,连续的最大喜好值是多少。
Input
第一行,n,花盆的数量
第二行,n个数,表示对于每盆花的喜好值。
第三行:m, 改动的次数
以下m行,每行两个数ki 和di 。
Output
M行,每一行对应一个更改,表示连续的最大喜好值,且不能整圈都选。(注意:是在圈上找)
Sample Input
5
3 -2 1 2 -5
4
2 -2
5 -5
2 -4
5 -1
Sample Output
4
4
3
5
题解:
对于20分,当然是用一个暴力过去啦~~~
对于30分,用O(nm)的动态规划,再加上卡常数就好了。
对于100分,此题满分做法涉及到线段树,不懂的可以去了解一下。
本题题意是数形成一个环状,又说了不可以全部数选择。那么,我们只需要求出1到n内最大的子区间和;从两边开始选的最大子区间和;1到n内最小的子区间和;从两边开始选的最小子区间和。因为我们要求出这样的东东:
那么,最优答案就是sum(表示数环的总和)-min或max。这时,我们用线段树来做这些操作,然后大体细节就好好看题,笔玩一下就可以推出线段树维护的规律。
来给个伪程序来维护max和min的操作:
{v为当前树的深度}
tree[v].sum:=tree[v*2].sum+tree[v*2+1].sum;{求sum值} tree[v].max:=max(max(tree[v*2].max,tree[v*2+1].max),tree[v*2].rgss+tree[v*2+1].lgss);{求max的值}
tree[v].lgss:=tree[v*2].lgss;{左边的maxlgss值}
tree[v].rgss:=tree[v*2+1].rgss;{右边的maxrgss值} tree[v].min:=min(min(tree[v*2].min,tree[v*2+1].min),tree[v*2].mrgss+tree[v*2+1].mlgss);{求min的值}
tree[v].mlgss:=tree[v*2].mlgss{求左边的minlgss值};
tree[v].mrgss:=tree[v*2+1].mrgss{求右边的minrgss值};
if(tree[v*2].lgss<tree[v*2].sum+tree[v*2+1].lgss) then
begin
tree[v].lgss:=tree[v*2].sum+tree[v*2+1].lgss;
end;
if(tree[v*2+1].rgss<tree[v*2+1].sum+tree[v*2].rgss) then
begin
tree[v].rgss:=tree[v*2+1].sum+tree[v*2].rgss;
end;
if(tree[v*2].mlgss>tree[v*2].sum+tree[v*2+1].mlgss) then
begin
tree[v].mlgss:=tree[v*2].sum+tree[v*2+1].mlgss;
end;
if(tree[v*2+1].mrgss>tree[v*2+1].sum+tree[v*2].mrgss) then
begin
tree[v].mrgss:=tree[v*2+1].sum+tree[v*2].mrgss;
end;
解答问题1:lgss和rgss有何用?答:这个可以时刻维护max的求值,具体维护法笔玩一下,这里不多说。(因为要说明就要画图)
解答问题2:如何判断有没有全部选。答:这是废话,只需要判断max值与sum值相不相等。
解答问题3:为什么sum要在树内做。答:这可以更好地去维护maxlgss、maxrgss、minlgss、minrgss的操作,当然时间会更快的问题我就不确定了。
解答问题4:线段树怎么做。答:自己研究。
标程:
type
new=record
max:longint;
lgss:longint;
rgss:longint;
min:longint;
mlgss:longint;
mrgss:longint;
sum:longint;
end;
var
i,j,k,l,n,m,t,r,x,gb,ans:longint;
a:array[0..1000000] of longint;
tree:array[0..1000000] of new;
bz:boolean;
function max(x,y:longint):longint;
begin
if x>y then exit(x)
else exit(y);
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x)
else exit(y);
end;
procedure maketree(x,st,en:longint);
var
m:longint;
begin
tree[x].max:=-50001;
tree[x].min:=50001;
tree[x].lgss:=-50001;
tree[x].rgss:=-50001;
tree[x].mlgss:=50001;
tree[x].mrgss:=-50001;
if st=en then
begin
exit;
end
else
begin
m:=(st+en) div 2;
maketree(x+x,st,m);
maketree(x+x+1,m+1,en);
end;
end;
procedure changenumber(v,x,l,r:longint);
var
i,j,mid:longint;
begin
if l=r then
begin
tree[v].max:=gb;
tree[v].min:=gb;
tree[v].lgss:=gb;
tree[v].rgss:=gb;
tree[v].mlgss:=gb;
tree[v].mrgss:=gb;
tree[v].sum:=gb;
exit;
end;
mid:=(r+l) div 2;
if x>mid then
begin
changenumber(v*2+1,x,mid+1,r);
end
else
if x<=mid then
begin
changenumber(v*2,x,l,mid);
end;
tree[v].sum:=tree[v*2].sum+tree[v*2+1].sum;
tree[v].max:=max(max(tree[v*2].max,tree[v*2+1].max),tree[v*2].rgss+tree[v*2+1].lgss);
tree[v].lgss:=tree[v*2].lgss;
tree[v].rgss:=tree[v*2+1].rgss;
tree[v].min:=min(min(tree[v*2].min,tree[v*2+1].min),tree[v*2].mrgss+tree[v*2+1].mlgss);
tree[v].mlgss:=tree[v*2].mlgss;
tree[v].mrgss:=tree[v*2+1].mrgss;
if(tree[v*2].lgss<tree[v*2].sum+tree[v*2+1].lgss) then
begin
tree[v].lgss:=tree[v*2].sum+tree[v*2+1].lgss;
end;
if(tree[v*2+1].rgss<tree[v*2+1].sum+tree[v*2].rgss) then
begin
tree[v].rgss:=tree[v*2+1].sum+tree[v*2].rgss;
end;
if(tree[v*2].mlgss>tree[v*2].sum+tree[v*2+1].mlgss) then
begin
tree[v].mlgss:=tree[v*2].sum+tree[v*2+1].mlgss;
end;
if(tree[v*2+1].mrgss>tree[v*2+1].sum+tree[v*2].mrgss) then
begin
tree[v].mrgss:=tree[v*2+1].sum+tree[v*2].mrgss;
end;
end;
begin
//assign(input,'xds.in');reset(input);
//assign(output,'xds.out');rewrite(output);
readln(n);
maketree(1,1,n);
for i:=1 to n do
begin
read(a[i]);
end;
for i:=1 to n do
begin
gb:=a[i];
changenumber(1,i,1,n);
end;
readln(m);
for k:=1 to m do
begin
readln(l,r);
gb:=r;
changenumber(1,l,1,n);
if(tree[1].max=tree[1].sum) then
begin
writeln(tree[1].max-tree[1].min);
continue;
end;
if(tree[1].max>=tree[1].sum-tree[1].min) then
begin
writeln(tree[1].max);
continue;
end;
if(tree[1].max<tree[1].sum-tree[1].min) then
begin
writeln(tree[1].sum-tree[1].min);
end;
end;
end.