TYVJ 1427 小白逛公园 线段树

自从上一次线段树写挂了以后,心里一直不爽!!!

线段树都能写挂。。。。

于是我又找了一些题。

因为临近noip了,就找了点简单题,难的没写出来,调试要花好久。。

我一旦做的题目错了,就会一直找错,直到3~4天都没发现才会放弃,浪费好多时间,于是不敢找难的

这个题目是动态求区间最大连续和,算是一道基本线段树吧= - =

只要记录从左边开始的最大值maxl,右边开始的最大值maxr,区间中的最大值max以及区间和sum

建树时,MAXL[k]:=max{maxl[k*2],sum[k*2]+maxl[k*2+1]} maxr[k]:=max{maxr[k*2+1],sum[k*2]+maxr[k*2]};

max[k]:=max{max[k*2],max[k*2+1],maxr[k*2]+maxl[k*2+1]};

然后修改时,思路一样,找到改的点,然后对从根到该节点所有路径做一遍建树的操作即可。

求答案时,我用了几个变参记录孩子在所给区间的maxl maxr max 以及sum (和数组不一样)用来更改本身节点的相应值,和建树时差不多。

= - =还有一个注意点,就是 会有读入x y y<x的情况= - =


code:(写的有点丑和长了= - =。。我觉得work和change能合在一起,然后边读入边change,但是这样时间会多一点。。)

var
  maxl,maxr,sum,max,zuo,you,a:array[0..1100000] of longint;
  z,ss,n,m,i,k,x,y,ll,rr,mm:longint;
function mx(a,b:longint):longint;
  begin
    if a>b then exit(a) else exit(b);
  end;

procedure work(k,l,r:longint);
  var
    m:longint;
  begin
    zuo[k]:=l;
	you[k]:=r;
	if (l=r) then
	  begin
	    max[k]:=a[l];
		maxl[k]:=a[l];
		maxr[k]:=a[l];
		sum[k]:=a[l];
	    exit;
	  end;
	m:=(l+r) div 2;
	work(k*2,l,m);
	work(k*2+1,m+1,r);
	max[k]:=mx(max[k*2],max[k*2+1]);
	max[k]:=mx(max[k],maxr[k*2]+maxl[k*2+1]);
    maxl[k]:=mx(maxl[k*2],sum[k*2]+maxl[k*2+1]);
	maxr[k]:=mx(maxr[k*2+1],sum[k*2+1]+maxr[k*2]);
	sum[k]:=sum[k*2]+sum[k*2+1];
  end;

procedure find(k,u,v:longint;var ll,rr,mm,ss:longint);
  var
    m,l,r,ll1,ll2,rr1,rr2,ss1,ss2,mm1,mm2:longint;
  begin
    l:=zuo[k];r:=you[k];
	if (l>=U) and (r<=v) then
	  begin
	    ll:=maxl[k];
		rr:=maxr[k];
		mm:=max[k];
		ss:=sum[k];
		exit;
	  end;
	m:=(l+r) div 2;
	ll:=-maxlongint;rr:=-maxlongint;mm:=-maxlongint;ss:=-maxlongint;
	ll1:=-maxlongint;rr1:=-maxlongint;mm1:=-maxlongint;ss1:=-maxlongint;
	ll2:=-maxlongint;rr2:=-maxlongint;mm2:=-maxlongint;ss2:=-maxlongint;
	if (u<=m) then find(k*2,u,v,ll1,rr1,mm1,ss1);
    if (v>m) then find(k*2+1,u,v,ll2,rr2,mm2,ss2);
	if (ll1>-maxlongint) and (ll2=-maxlongint) then 
	  begin
	    ll:=ll1;
		rr:=rr1;
		mm:=mm1;
		ss:=ss1;
	  end;
	if (ll1=-maxlongint) and (ll2>-maxlongint) then 
	  begin
	    ll:=ll2;
		rr:=rr2;
		mm:=mm2;
		ss:=ss2;
	  end;	
    if (ll1>-maxlongint) and (ll2>-maxlongint) then
	  begin
	    ll:=mx(ll1,ss1+ll2);
		rr:=mx(rr2,ss2+rr1);
		mm:=mx(mm1,mm2);
		mm:=mx(mm,rr1+ll2);
		ss:=ss1+ss2;
	  end;
  end;
procedure change(k,x,y:longint);
  var
    l,r,m:longint;
  begin
    l:=zuo[k];
	r:=you[k];
	if (l=x) and (l=r) then
	  begin
	    max[k]:=y;
		maxl[k]:=y;
		maxr[k]:=y;
		sum[k]:=y;
	    exit;
	  end;
	m:=(l+r) div 2;
	if x<=m then change(k*2,x,y);
	if x>m then change(k*2+1,x,y);
	max[k]:=mx(max[k*2],max[k*2+1]);
	max[k]:=mx(max[k],maxr[k*2]+maxl[k*2+1]);
    maxl[k]:=mx(maxl[k*2],sum[k*2]+maxl[k*2+1]);
	maxr[k]:=mx(maxr[k*2+1],sum[k*2+1]+maxr[k*2]);
	sum[k]:=sum[k*2]+sum[k*2+1];
  end;

begin
  read(n,m);
  for i:=1 to n do
	read(a[i]);
  work(1,1,n);
  for i:=1 to m do
    begin
	  read(k);
	  if k=1 then
	    begin
		  read(x,y);
		  if y<x then 
		    begin
			  z:=x;
			  x:=y;
			  y:=z;
			end;
		  find(1,x,y,ll,rr,mm,ss);
		  writeln(mm);
		end;
	  if k=2 then
	    begin
		  read(x,y);
		  change(1,x,y);
		end;
	end;
end.
	  

最后所有数据一共花了3.7s 好像一点慢了些。。。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值