您的位置:首页 > 其它

【二维线段树】poi2006 tet

2011-03-15 09:43 211 查看
题目大意

给你一个1000*1000的矩阵,支持两种操作:

1.查询一个子矩阵的最大值;

2.把一个子矩阵的值全部改为某一个值;

ps:矩阵内所有值递增;

一开始没有什么好idea,以前就想过关于二维线段树标记下放的问题,后来才明白了二维线段树在第一维上是不能下方标记的。

写了个很挫的四分树,TLE了。。

program ex1;
{$inline+}
const mm=2100;
var
f,s:array[0..mm*mm] of longint;
i,n,h,x1,y1,x2,y2,mh:longint;
procedure find(i,l1,r1,l2,r2:longint);inline;var t,m1,m2:longint;
begin
if f[i]<=mh then exit;
if (x1>l1)or(y1<r1)or(x2>l2)or(y2<r2) then begin
t:=i<<2;
m1:=(l1+r1)>>1;m2:=(l2+r2)>>1;
if (x1<=m1)and(x2<=m2) then find(t,l1,m1,l2,m2);
if (x1<=m1)and(y2>m2) then find(t+1,l1,m1,m2+1,r2);
if (y1>m1)and(x2<=m2) then find(t+2,m1+1,r1,l2,m2);
if (y1>m1)and(y2>m2) then find(t+3,m1+1,r1,m2+1,r2);
if s[i]>mh then mh:=s[i];
end else if f[i]>mh then mh:=f[i];
end;
procedure cover(i,l1,r1,l2,r2:longint);inline;var t,m1,m2:longint;
begin
if (x1>l1)or(y1<r1)or(x2>l2)or(y2<r2) then begin
t:=i<<2;
m1:=(l1+r1)>>1;m2:=(l2+r2)>>1;
if (x1<=m1)and(x2<=m2) then cover(t,l1,m1,l2,m2);
if (x1<=m1)and(y2>m2) then cover(t+1,l1,m1,m2+1,r2);
if (y1>m1)and(x2<=m2) then cover(t+2,m1+1,r1,l2,m2);
if (y1>m1)and(y2>m2) then cover(t+3,m1+1,r1,m2+1,r2);
end else s[i]:=h;
if h>f[i] then f[i]:=h;
end;
begin
readln(n,n,n);
for i:=1 to n do begin
readln(y1,y2,h,x1,x2);
inc(y1,x1);inc(y2,x2);
inc(x1);inc(x2);mh:=0;
find(1,1,1024,1,1024);
inc(h,mh);
cover(1,1,1024,1,1024);
end;
writeln(f[1]);
end.


看了GHY的code才知道其实标记完全不需要下放,介于这道题的特殊性,标记具有了交换律和结合律,在第二维上维护两个线段树,一个关于标记的线段树,一个关于区间最大值的线段树即可。

h8oj RANK1:

program tet;{$inline+}
type arr=array[0..2048,0..1] of longint;
var
f,s:array[0..2048] of arr;
i,n,h,x1,y1,x2,y2,xx,yy,mh:longint;
procedure find(i,l,r:longint;var f:arr);inline;var m,t:longint;
begin
if (x2>l)or(y2<r) then begin
m:=(l+r)>>1;t:=i+i;
if mh<f[i,1] then mh:=f[i,1];
if x2<=m then find(t,l,m,f);
if m<y2 then find(t+1,m+1,r,f);
end else if mh<f[i,0] then mh:=f[i,0];
end;
procedure cover(i,l,r:longint;var f:arr);inline;var m,t:longint;
begin
if h>f[i,0] then f[i,0]:=h;
if (x2>l)or(y2<r) then begin
m:=(l+r)>>1;t:=i+i;
if x2<=m then cover(t,l,m,f);
if m<y2 then cover(t+1,m+1,r,f);
end else if h>f[i,1] then f[i,1]:=h;
end;
procedure find(i,l,r:longint);inline;var m,t:longint;
begin
if (x1>l)or(y1<r) then begin
m:=(l+r)>>1;t:=i+i;
find(1,1,yy,s[i]);
if x1<=m then find(t,l,m);
if m<y1 then find(t+1,m+1,r);
end else find(1,1,yy,f[i]);
end;
procedure cover(i,l,r:longint);inline;var m,t:longint;
begin
cover(1,1,yy,f[i]);
if (x1>l)or(y1<r) then begin
m:=(l+r)>>1;t:=i+i;
if x1<=m then cover(t,l,m);
if m<y1 then cover(t+1,m+1,r);
end else cover(1,1,yy,s[i]);
end;
begin
readln(xx,yy,n);
for i:=1 to n do begin
readln(y1,y2,h,x1,x2);
inc(y1,x1);inc(y2,x2);
inc(x1);inc(x2);mh:=0;
find(1,1,xx);
inc(h,mh);
cover(1,1,xx);
end;
writeln(f[1,1,0]);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: