线段树 例六 未解决

题目大意

  在一个N*N的方格中,开始每个格子里的数都是0。现在动态地提出一些问题和修改:提问的形式是求某一个特定的子矩阵(x1,y1)-(x2,y2)中所有元素的和;修改的规则是指定某一个格子(x,y),在(x,y)中的格子元素上加上或者减去一个特定的值A。现在要求你能对每个提问作出正确的回答。1≤N≤1024,提问和修改的总数可能达到60000条。

 

分析

  我有一个超时的算法:把每一行都建一棵线段树(f[x])(x为行)(f[x]为一行的情况)

  统计(x,y)(x1,y1)时把f[x]…f[x1]的线段树区间[y,y1]加在一起。

  但超时。

type
  pnode=^tnode;
  tnode=record
    lc,rc:pnode;
    c:longint;
end;

var
  f:array[0..1200] of pnode;
  i,j,k:longint;
  x,y,x1,y1:longint;
  n,m:longint;
  co:longint;
  s:longint;
  ans:longint;

procedure neww(var t:pnode);
begin
  if t=nil then
    begin
      new(t);
      t^.c:=0;
      t^.lc:=nil;
      t^.rc:=nil;
    end;
end;

procedure insert(var t:pnode; l,r,x,y,co:longint);
var
  i,j,k:longint;
  mid:longint;

begin
  with t^ do
    begin
      {if c=0 then
        begin   }
          c:=c+co;
          mid:=(l+r) div 2;
          if (l=x) and (r=y)
            then
              exit;
          if (l<=x) and (mid>=y)
            then
              begin
                neww(lc);
                insert(lc,l,mid,x,y,co);
                exit;
              end;
          if (mid<x) and (r>=y)
            then
              begin
                neww(rc);
                insert(rc,mid+1,r,x,y,co);
                exit;
              end;
          neww(lc);
          neww(rc);
          insert(lc,l,mid,x,mid,co);
          insert(rc,mid+1,r,mid+1,y,co);
        end;
    {end;}
end;

function find(t:pnode;l,r,x,y:longint):longint;
var
  mid:longint;
begin
  if t=nil then exit(0);
  with t^ do
    begin
      mid:=(l+r) div 2;
      if (l=x) and (r=y)
        then
          begin
            find:=c;
            exit;
          end;
      if (l<=x) and (mid>=y)
        then
          begin
            find:=find(lc,l,mid,x,y);
            exit;
          end;
      if (mid<x) and (r>=y)
        then
          begin
            find:=find(rc,mid+1,r,x,y);
            exit;
          end;
      find:=find(lc,l,mid,x,mid)+find(rc,mid+1,r,mid+1,y);
    end;
end;

begin
  readln(i,m);
  m:=m-1;
  while not eof do
    begin
      read(s);
      if s>=3 then break;
      if s=1
        then
          begin
            readln(x,y,co);
            neww(f[x]);
            insert(f[x],0,m,y,y,co);
          end
        else
          begin
            readln(x,y,x1,y1);
            ans:=0;
            for i:=x to x1 do
              begin
                neww(f[i]);
                ans:=ans+find(f[i],0,m,y,y1);
              end;
            writeln(ans);
          end;
    end;
end.


posted @ 2016-05-19 18:03  一个响亮的蒟蒻  阅读(77)  评论(0编辑  收藏  举报