bzoj 3132 二维树状数组

版权声明:本文为博主原创文章,转载时请注明原文地址=w=,希望对您有所帮助 https://blog.csdn.net/Eirlys_North/article/details/71157608

题意:一个n*m初始为空的矩阵,资磁两种操作:(1)某个子矩阵的值都增加c (2)输出某个子矩阵的权值和

用a[i,j]表示(i,j)~(n,m)的增量,则对于(1,1)~(x,y)的权值和ans

ans=sigma(a[i,j]*(x-i+1)*(y-j+1))(1<=i<=x,1<=j<=y)

      =sigma(a[i,j]*(x+1)*(y+1)-j*(x+1)*a[i,j]-i*(y+1)*a[i,j]+i*j*a[i,j])  (1<=i<=x,1<=j<=y)

      =(x+1)*(y+1)*sigma(a[i,j])-(x+1)*sigma(j*a[i,j])-(y+1)*sigma(i*a[i,j])+sigma(i*j*a[i,j])  (1<=i<=x,1<=j<=y)

维护四个树状数组分别为 

1:sigma(a[i,j])

2:sigma(j*a[i,j])

3:sigma(i*a[i,j])

4:sigma(i*j*a[i,j])

{$Q-}
var
        n,m,x1,x2,y1,y2,c       :longint;
        ch                      :char;
        t                       :array[0..4,0..2105,0..2105] of longint;

procedure _add(z,x,y,v:longint);
var
        tt:longint;
begin
   while x<=n do
   begin
      tt:=y;
      while tt<=m do
      begin
         inc(t[z,x,tt],v);
         inc(tt,tt and (-tt));
      end;
      inc(x,x and (-x));
   end;
end;

procedure change(x1,y1,x2,y2,c:longint);
begin
   _add(1,x1,y1,c);
   _add(1,x2+1,y2+1,c);
   _add(1,x1,y2+1,-c);
   _add(1,x2+1,y1,-c);
   //
   _add(2,x1,y1,y1*c); _add(3,x1,y1,x1*c);
   _add(2,x2+1,y2+1,(y2+1)*c); _add(3,x2+1,y2+1,(x2+1)*c);
   _add(2,x1,y2+1,-(y2+1)*c); _add(3,x1,y2+1,-x1*c);
   _add(2,x2+1,y1,-y1*c); _add(3,x2+1,y1,-(x2+1)*c);
   //
   _add(4,x1,y1,x1*y1*c);
   _add(4,x2+1,y2+1,(x2+1)*(y2+1)*c);
   _add(4,x1,y2+1,-x1*(y2+1)*c);
   _add(4,x2+1,y1,-(x2+1)*y1*c);
end;

function find(z,x,y:longint):longint;
var
        tt,ans:longint;
begin
   ans:=0;
   while x>0 do
   begin
      tt:=y;
      while tt>0 do
      begin
         inc(ans,t[z,x,tt]);
         dec(tt,tt and (-tt));
      end;
      dec(x,x and (-x));
   end;
   exit(ans);
end;

function sum(x,y:longint):longint;
begin
   exit(find(1,x,y)*(x+1)*(y+1)-(x+1)*find(2,x,y)-(y+1)*find(3,x,y)+find(4,x,y));
end;

begin
   read(ch);
   readln(n,m);
   while not eof do
   begin
      read(ch);
      if ch='L' then
      begin
         readln(x1,y1,x2,y2,c);
         change(x1,y1,x2,y2,c);
      end else
      begin
         readln(x1,y1,x2,y2);
         writeln(sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1-1,y1-1));
      end;
   end;
end.
——by Eirlys



猜你喜欢

转载自blog.csdn.net/Eirlys_North/article/details/71157608