三角形

题目描述 给定一个三角形数阵,第一行有一个数,第二行有两个数,直到第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.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值