题目描述 给定一个三角形数阵,第一行有一个数,第二行有两个数,直到第n行有n个数。一开始,每个数的值都是0。 你需要支持以下两个操作:
1、将一个子三角数阵里的数全部加一。 2、询问一个子三角数阵里的数的和。 我们将以三元组(x, y, a)来描述一个子三角形数阵。
这个数阵中的第一行的元素是(x, y)。 共有a行,第i行从(x+i-1, y)到(x+i-1, y+i-1)。 注意:(x,
y)表示第x行的第y个数。 输入 输入文件为delta.in。 第一行,两个整数N和Q,代表三角形的规模和操作数。
以下Q行,每行都是“操作类型编号 xi yi ai”的格式。 输出 输出文件为delta.out。
对于每个2类操作,输出一行包含一个整数作为答案。
样例输入
3 9
2 1 1 2
1 1 1 2
2 1 1 2
1 2 1 2
2 1 1 2
2 2 2 2
1 2 2 2
2 1 1 2
2 1 1 3
样例输出
0
3
4
2
5
9
提示
对于10%的测试数据,满足n<=10,Q<=10^5。 对于另外20%的测试数据,满足N<=100,Q<=10^5 。
对于另外20%的测试数据,满足N<=1000,Q<=10^4 。 对于另外20%的测试数据,满足所有的1类操作在2类操作之前。
对于100%的数据,满足1<=N<=1000,1<=Q<=10^5 。
三角形的图形想要快速修改几乎不可能。
记录每一千次修改,再总的修改,记录前缀和。
对于计算重叠部分面积,可以实现O(1)计算。详见代码。
const sz=1000;
var
tag:array[0..1005,0..1005] of longint;
sum:array[0..1005,0..1005] of int64;
x,y,l:array[0..1005] of longint;
i,j,n,q,num,a,b,c,aa,bb,cc,opt,mx:longint;
ans,len:int64;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
procedure rebuild;
var
a,b,c,mx,i,j,t:longint;
now,now2:int64;
begin
fillchar(tag,sizeof(tag),0);
for t:=1 to num do
begin
a:=x[t];
b:=y[t];
c:=l[t];
mx:=a+c;
j:=a;
for i:=b to b+c-1 do
begin
tag[i,j]:=tag[i,j]+1;
tag[i,mx]:=tag[i,mx]-1;
j:=j+1;
end;
end;
for i:=1 to n do
begin
now:=0;
now2:=0;
for j:=i to n do
begin
now:=now+tag[i,j];
now2:=now2+now;
sum[i,j]:=sum[i,j]+now2;
end;
end;
num:=0;
end;
begin
readln(n,q);
while q>0 do
begin
q:=q-1;
read(opt);
if opt=1 then
begin
num:=num+1;
readln(x[num],y[num],l[num]);
if num=sz then rebuild;
end
else
begin
readln(a,b,c);
j:=a-1;
ans:=0;
mx:=a+c-1;
for i:=b to b+c-1 do
begin
ans:=ans+sum[i,mx]-sum[i,j];
j:=j+1;
end;
for i:=1 to num do
begin
aa:=min(a+c-1,x[i]+l[i]-1);
bb:=max(b,y[i]);
cc:=max(a-b,x[i]-y[i]);
if (a>aa)or(x[i]>aa) then continue;
if (b+c-1<bb)or(y[i]+l[i]-1<bb) then continue;
if (a+c-1-b<cc)or(x[i]+l[i]-1-y[i]<cc) then continue;
len:=aa-bb-cc+1;
ans:=ans+len*(len+1) div 2;
end;
writeln(ans);
end;
end;
end.