2017.2.12【初中部 GDKOI】模拟赛B组 T4:pot

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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值