每个输入文件有多行。
第一行,一个数n,表示鼹鼠的范围。
以后每一行开头都有一个数m,表示不同的操作:
m=1,那么后面跟着3个数x,y,k(0<=x,y<n),表示在点(x,y)处新出现了k只鼹鼠;
m=2,那么后面跟着4个数x1,y1,x2,y2(0<=x1<=x2<n,0<=y1<=y2<n),表示询问矩形(x1,y1)-(x2,y2)内的鼹鼠数量;
m=3,表示老师来了,不能玩了。保证这个数会在输入的最后一行。
询问数不会超过10000,鼹鼠数不会超过maxlongint。n<=1024
测试数据 #1: Accepted, time=0ms, mem=98806KB, score=10
测试数据 #2: Accepted, time=124ms, mem=98806KB, score=10
测试数据 #3: Accepted, time=15ms, mem=98806KB, score=10
测试数据 #4: Accepted, time=15ms, mem=98806KB, score=10
测试数据 #5: Accepted, time=109ms, mem=98806KB, score=10
测试数据 #6: Accepted, time=0ms, mem=98806KB, score=10
测试数据 #7: Accepted, time=62ms, mem=98806KB, score=10
测试数据 #8: Accepted, time=31ms, mem=98806KB, score=10
测试数据 #9: Accepted, time=15ms, mem=98802KB, score=10
测试数据 #10: Accepted, time=140ms, mem=98806KB, score=10
Time = 511ms Mem = 98806KB Score= 100
这道题虽然是单点,但我写的是区间。(其实用树状数组做更快……只是用来试模板= =)
二维线段树注意以下几个方面:
- X树更新时时要到底到叶节点(因为X树不能lazy),但查询时不用查到叶节点(= =因此tle了若干次)。
- y树可以lazy,方法和普通线段树一样。
- 二维线段树的内存占用= =
- mid取得是xl xr,而不是要查询的区间x1、x2
Code
program segtree2D;
//Accepted
type
rec=record
xl,xr,yl,yr:integer;
add,sum:longint;
end;
Var
f:array[0..3100,0..3100] of rec;
n,m,i,j,x,y,k,x1,x2,y1,y2,op,top:longint;
Function mmin(a,b:longint):longint;inline;begin if a<b then exit(a);exit(b); end;
Function mmax(a,b:longint):longint;inline;begin if a>b then exit(a);exit(b); end;
Procedure buildY(p,q:longint);
var
mid:longint;
begin
if q>top then top:=q;
if f[p,q].yl=f[p,q].yr then exit;
mid:=(f[p,q].yl+f[p,q].yr) div 2;
with f[p,q*2] do
begin
xl:=f[p,q].xl;
xr:=f[p,q].xr;
yl:=f[p,q].yl;
yr:=mid;
end;
buildy(p,q*2);
with f[p,q*2+1] do
begin
xl:=f[p,q].xl;
xr:=f[p,q].xr;
yl:=mid+1;
yr:=f[p,q].yr;
end;
buildY(p,q*2+1);
end;
Procedure buildx(P:longint);
var
mid:longint;
begin
f[p,1].yl:=0;f[p,1].yr:=n-1;
buildy(p,1);
if f[p,1].xl=f[p,1].xr then exit;
mid:=(f[p,1].xl+f[p,1].xr) div 2;
with f[p*2,1] do
begin
xl:=f[p,1].xl;
xr:=mid;
end;
buildx(p*2);
with f[p*2+1,1] do
begin
xl:=mid+1;
xr:=f[p,1].xr;
end;
buildx(p*2+1);
end;
Procedure pushdown(p,q:longint);
begin
if p>top then exit;
//writeln('push down ',p,' ',q,' #:',f[p,q].add);
if q*2<=top then begin
inc(f[p,q*2].sum,(f[p,q*2].yr-f[p,q*2].yl+1)*f[p,q].add);
inc(f[p,q*2].add,f[p,q].add); end;
if q*2+1<=top then begin
inc(f[p,q*2+1].sum,(f[p,q*2+1].yr-f[p,q*2+1].yl+1)*f[p,q].add);
inc(f[p,q*2+1].add,f[p,q].add); end;
f[p,q].add:=0;
end;
Procedure addy(p,q,x1,x2,y1,y2,k:longint);
var
mid:longint;
begin
pushdown(p,q);
with f[p,q] do
begin
if (yl=y1) and (yr=y2) then
begin
inc(sum,(yr-yl+1)*(x2-x1+1)*k);
inc(add,k*(x2-x1+1));
exit;
end;
mid:=(yl+yr) shr 1;
if y1<=mid then addy(p,q*2,x1,x2,y1,mmin(y2,mid),k);
if y2>mid then addy(p,q*2+1,x1,x2,mmax(y1,mid+1),y2,k);
f[p,q].sum:=f[p,q*2].sum+f[p,q*2+1].sum;
end;
end;
Procedure Addx(P,x1,y1,x2,y2,k:longint);
var
mid:longint;
begin
Addy(p,1,x1,x2,y1,y2,k);
if (f[p,1].xr=f[p,1].xl) then exit;
with f[p,1] do mid:=(xl+xr) div 2;
if x1<=mid then Addx(p*2,x1,y1,mmin(x2,mid),y2,k);
if x2>mid then Addx(p*2+1,mmax(mid+1,x1),y1,x2,y2,k);
end;
Function getsumy(p,q,x1,x2,y1,y2:longint):longint;
var
mid:longint;
begin
pushdown(p,q); getsumy:=0;
with f[p,q] do
if (yl=y1) and (yr=y2) then
begin
//writeln('straight got!',yl,' ',yr,' ',f[p,q].sum);
exit(f[p,q].sum)
end
else
begin
mid:=(yl+yr) shr 1;
if y1<=mid then inc(getsumy,getsumy(p,q*2,x1,x2,y1,mmin(y2,mid)));
if y2>mid then inc(getsumy,getsumy(p,q*2+1,x1,x2,mmax(y1,mid+1),y2));
end;
//writeln('getsumY',p,' ',x1,',',y1,' | ',x2,',',y2,' =',getsumy);
end;
Function getsumX(p,x1,y1,x2,y2:longint):longint;
var
mid:longint;
begin
getsumx:=0;
with f[p,1] do
if (xl=x1) and (xr=x2) then
inc(getsumx,getsumy(p,1,x1,x2,y1,y2))
else
begin
mid:=(xl+xr) shr 1;
if x1<=mid then inc(getsumx,getsumx(p*2,x1,y1,mmin(x2,mid),y2));
if x2>mid then inc(getsumx,getsumx(p*2+1,mmax(mid+1,x1),y1,x2,y2));
end;
//writeln('getsumX',p,' ',x1,',',y1,' | ',x2,',',y2,' =',getsumx);
end;
Procedure init(N:longint);
begin
with f[1,1] do
begin
xl:=0;
xr:=n-1;
end;
Buildx(1);
end;
begin
readln(n);
init(n);
top:=0;
while true do
begin
read(op);
case op of
1:
begin
readln(x,y,k);
AddX(1,x,y,x,y,k);
end;
2:
begin
readln(x1,y1,x2,y2);
writeln(getsumX(1,x1,y1,x2,y2));
end;
3:
halt;
end;
end;
end.