zoukankan      html  css  js  c++  java
  • [TyvjP1474]二维线段树区间更新+查询

    每个输入文件有多行。
    第一行,一个数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.
    
  • 相关阅读:
    洛谷P2798 爆弹虐场
    洛谷P1164 小A点菜(01背包求方案数)
    洛谷P1312 Mayan游戏
    洛谷P1514 引水入城
    2017-10-12 NOIP模拟赛
    洛谷P1038 神经网络
    洛谷P1607 [USACO09FEB]庙会班车Fair Shuttle
    洛谷P1378 油滴扩展
    Ionic+Angular实现中英国际化(附代码下载)
    Ionic+Angular+Express实现前后端交互使用HttpClient发送get请求数据并加载显示(附代码下载)
  • 原文地址:https://www.cnblogs.com/htfy/p/3073793.html
Copyright © 2011-2022 走看看