• 线段树(可能还会有树状数组吧)


    看了下gdkoi2014……觉得完蛋了……除了一道莫队还可以写写一眼看出,其他基本不行……

    发现学了一大堆东西都不会用……

    那就从最基础的线段树还是吧。

    都说了只是开坑还没写呢⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄

    POJ - 1151 Atlantis

    妈蛋,都不会写线段树了……这道傻叉题竟然写了一个早上+一个下午&……

    以前学的时候就一直搞乱云说的点树和区间树的区别。

    都怪自己弱呵呵。

    这道题竟然用lazy了……我到底是有多傻逼&(然后看了别人的代码终于醒悟)

    type
      arr1=record
        left,right,tot,mark:longint;
        sum:double;
      end;
      arr2=record
        x,y1,y2:double;
        col:longint;
      end;
    
    const
      maxn=300000;
    
    var
      tree:array[0..maxn]of arr1;
      line:array[0..maxn]of arr2;
      hash,long:array[0..maxn]of double;
      num:array[0..maxn]of longint;
      total,n,t:longint;
    
    procedure qsort1(l,r:longint);
    var
      i,j:longint;
      mid,tmp:double;
    begin
      i:=l;
      j:=r;
      mid:=hash[(l+r)>>1];
      repeat
        while hash[i]<mid do inc(i);
        while hash[j]>mid do dec(j);
        if i<=j then begin
          tmp:=hash[i];
          hash[i]:=hash[j];
          hash[j]:=tmp;
          inc(i);
          dec(j);
        end;
      until i>j;
      if i<r then qsort1(i,r);
      if l<j then qsort1(l,j);
    end;
    
    procedure qsort2(l,r:longint);
    var
      i,j:longint;
      mid:double;
      tmp:arr2;
    begin
      i:=l;
      j:=r;
      mid:=line[(l+r)>>1].x;
      repeat
        while line[i].x<mid do inc(i);
        while line[j].x>mid do dec(j);
        if i<=j then begin
          tmp:=line[i];
          line[i]:=line[j];
          line[j]:=tmp;
          inc(i);
          dec(j);
        end;
      until i>j;
      if i<r then qsort2(i,r);
      if l<j then qsort2(l,j);
    end;
    
    function find(x:double):longint;
    var
      left,right,mid:longint;
    begin
      left:=1;
      right:=total+1;
      while left+1<right do begin
        mid:=(left+right)>>1;
        if long[mid]=x then exit(mid);
        if long[mid]<x then left:=mid
          else right:=mid;
      end;
      exit(left);
    end;
    
    procedure build(x,l,r:longint);
    var
      mid:longint;
    begin
      tree[x].sum:=0;
      tree[x].left:=l;
      tree[x].right:=r;
      tree[x].tot:=0;
      mid:=(l+r)>>1;
      if l+1=r then exit;
      build(x<<1,l,mid);
      build(x<<1+1,mid,r);
    end;
    
    procedure update(x:longint);
    begin
      if tree[x].tot>0 then
        tree[x].sum:=long[tree[x].right]-long[tree[x].left]
      else
        if tree[x].right-tree[x].left=1 then tree[x].sum:=0
          else
            tree[x].sum:=tree[x<<1].sum+tree[x<<1+1].sum;
    end;
    
    procedure change(x,ll,rr,y:longint);
    var
      mid:longint;
    begin
      if (tree[x].left=ll) and (tree[x].right=rr) then begin
        inc(tree[x].tot,y);
        update(x);
        exit;
      end;
      mid:=(tree[x].left+tree[x].right)>>1;
      if ll>=mid then change(x<<1+1,ll,rr,y)
        else
          if rr<=mid then change(x<<1,ll,rr,y)
            else begin
              change(x<<1,ll,mid,y);
              change(x<<1+1,mid,rr,y);
            end;
      update(x);
    end;
    
    procedure into;
    var
      i:longint;
      x1,y1,x2,y2,yy:double;
    begin
      for i:=1 to n do begin
        readln(x1,y1,x2,y2);
        line[i<<1-1].x:=x1;
        line[i<<1-1].y1:=y1;
        line[i<<1-1].y2:=y2;
        line[i<<1]:=line[i<<1-1];
        line[i<<1-1].col:=1;
        line[i<<1].col:=-1;
        line[i<<1].x:=x2;
        hash[i<<1-1]:=y1;
        hash[i<<1]:=y2;
      end;
      qsort1(1,n<<1);
      total:=1;
      num[1]:=1;
      long[1]:=hash[1];
      for i:=2 to n<<1 do begin
        if hash[i]<>hash[i-1] then begin
          inc(total);
          long[total]:=hash[i];
        end;
        num[i]:=total;
      end;
      qsort2(1,n<<1);
      build(1,1,total);
    end;
    
    procedure work;
    var
      i,j:longint;
      ans:double;
    begin
      ans:=0;
      for i:=1 to n<<1-1 do begin
        change(1,find(line[i].y1),find(line[i].y2),line[i].col);
        if line[i].x<>line[i+1].x then
          ans:=ans+(line[i+1].x-line[i].x)*tree[1].sum;
      end;
      writeln('Test case #',t);
      writeln('Total explored area: ',ans:0:2);
      writeln;
    end;
    
    begin
      t:=0;
      while true do begin
        readln(n);
        if n=0 then break;
        inc(t);
        into;
        work;
      end
    end.
    View Code

    最后还被格式小小得坑了……&

    点树和区间树区别在于[l,r]的两个儿子区间,如果是点树是[l,mid][mid+1,r]边界条件是l=r而区间树则是[l,mid][mid,r]边界条件是l+1=r。

    bzoj 3306: 树

    出题人什么心态,没写数据范围,害我以为是我的程序错了……

    这题是bzoj3083的弱化版……我竟然还写了那么久

    后来拿3083的程序(当时的题解http://hi.baidu.com/macaulish64/item/33fd9adbbb21b80738f6f746)交&……发现速度差不多……我的树链这么快么?

    不说了竟然弱到这个地步

    type
      arr1=record
        left,right:longint;
        min:int64;
      end;
      arr2=record
        toward,next:longint;
      end;
     
    const
      maxn=400600;
     
    var
      tree:array[0..maxn]of arr1;
      edge:array[0..maxn]of arr2;
      numin,numout,first,deep:array[0..maxn]of longint;
      hash,value:array[0..maxn]of int64;
      fa:array[0..maxn,0..20]of longint;
      n,root,esum,m,mm,time:longint;
     
    function min(x,y:int64):int64;
    begin
      if x<y then exit(x);
      exit(y);
    end;
     
    procedure addedge(i,j:longint);
    begin
      inc(esum);
      edge[esum].toward:=j;
      edge[esum].next:=first[i];
      first[i]:=esum;
    end;
     
    procedure swap(var x,y:longint);
    var
      i:longint;
    begin
      i:=x;
      x:=y;
      y:=i;
    end;
     
    procedure dfs(x:longint);
    var
      i,too:longint;
    begin
      inc(time);
      numin[x]:=time;
      hash[time]:=value[x];
      i:=first[x];
      while i>0 do begin
        too:=edge[i].toward;
        deep[too]:=deep[x]+1;
        dfs(too);
        i:=edge[i].next;
      end;
      numout[x]:=time;
    end;
     
    procedure build(x,l,r:longint);
    var
      mid:longint;
    begin
      tree[x].left:=l;
      tree[x].right:=r;
      if l=r then begin
        tree[x].min:=hash[l];
        exit;
      end;
      tree[x].min:=maxlongint<<3;
      mid:=(l+r)>>1;
      build(x<<1,l,mid);
      build(x<<1+1,mid+1,r);
      tree[x].min:=min(tree[x<<1].min,tree[x<<1+1].min);
    end;
     
    procedure change(x,y:longint;z:int64);
    var
      mid:longint;
    begin
      if (tree[x].left=y) and (tree[x].right=y) then begin
        tree[x].min:=z;
        exit;
      end;
      mid:=(tree[x].left+tree[x].right)>>1;
      if y<=mid then change(x<<1,y,z)
        else change(x<<1+1,y,z);
      tree[x].min:=min(tree[x<<1].min,tree[x<<1+1].min);
    end;
     
    function askmin(x,l,r:longint):int64;
    var
      mid:longint;
    begin
      if (tree[x].left=l) and (tree[x].right=r) then exit(tree[x].min);
      mid:=(tree[x].left+tree[x].right)>>1;
      if l>mid then exit(askmin(x<<1+1,l,r))
      else
        if r<=mid then exit(askmin(x<<1,l,r))
        else
          exit(min(askmin(x<<1,l,mid),askmin(x<<1+1,mid+1,r)));
    end;
     
    function lca(x,y:longint):longint;
    var
      i:longint;
    begin
      if deep[x]<deep[y] then swap(x,y);
      for i:=mm downto 0 do
        if deep[y]+1<=deep[fa[x,i]] then
          x:=fa[x,i];
      if y=fa[x,0] then exit(x)
        else x:=fa[x,0];
      for i:=mm downto 1 do
        if fa[x,i]<>fa[y,i] then begin
          x:=fa[x,i];
          y:=fa[y,i];
        end;
      exit(x);
    end;
     
    procedure into;
    var
      i,j:longint;
    begin
      readln(n,m);
      for i:=1 to n do begin
        readln(fa[i,0],value[i]);
        if fa[i,0]=0 then root:=i
          else addedge(fa[i,0],i);
      end;
      deep[root]:=1;
      dfs(root);
      build(1,1,n);
      mm:=trunc(ln(n)/ln(2))+1;
      for j:=1 to mm do
        for i:=1 to n do
          fa[i,j]:=fa[fa[i,j-1],j-1];
    end;
     
    procedure work;
    var
      ch:char;
      x,i:longint;
      l:int64;
    begin
      while m>0 do begin
        dec(m);
        read(ch);
        if ch='Q' then begin
          readln(x);
          if x=root then writeln(tree[1].min)
          else begin
            i:=lca(root,x);
            if fa[i,0]<>x then writeln(askmin(1,numin[x],numout[x]))
            else
              if numout[i]<n then
                writeln(min(askmin(1,1,numin[i]-1),askmin(1,numout[i]+1,n)))
              else writeln(askmin(1,1,numin[i]-1));
          end;
        end
        else
        if ch='V' then begin
          readln(i,l);
          change(1,numin[i],l);
        end
        else readln(root);
      end;
    end;
     
    begin
      into;
      work
    end.
    View Code

    UVA 11297 Census

     二维线段树裸题,单点修改,区间查询

    半小时敲完不用调直接1a我也是蛮拼的

    算是第一次敲二维线段树(虽然不难);

    二维线段树要注意的就是大树到小树,而小树节点也要根据大树的叶节点进行调整

    好累(但是rausen大神一天切好多题啊)

    type
      arr1=record
        left,right:longint;
      end;
      arr2=record
        left,right,min,max:longint;
      end;
    
    const
      maxn=4000;
    
    var
      tree1:array[0..maxn]of arr1;
      tree2:array[0..maxn,0..maxn]of arr2;
      a:array[0..505,0..505]of longint;
      x1,x2,y1,y2,n,m,ansmin,ansmax:longint;
    
    
    function max(x,y:longint):longint;
    begin
      if x<y then exit(y);
      exit(x);
    end;
    
    function min(x,y:longint):longint;
    begin
      if x<y then exit(x);
      exit(y);
    end;
    
    procedure buildsmall(x0,x,l,r:longint);
    var
      mid:longint;
    begin
      tree2[x0][x].left:=l;
      tree2[x0][x].right:=r;
      if l=r then begin
        if tree1[x0].left=tree1[x0].right then begin
          tree2[x0][x].min:=a[tree1[x0].left][l];
          tree2[x0][x].max:=tree2[x0][x].min;
        end
        else begin
          tree2[x0][x].min:=min(tree2[x0<<1][x].min,tree2[x0<<1+1][x].min);
          tree2[x0][x].max:=max(tree2[x0<<1][x].max,tree2[x0<<1+1][x].max);
        end;
        exit;
      end;
      mid:=(l+r)>>1;
      buildsmall(x0,x<<1,l,mid);
      buildsmall(x0,x<<1+1,mid+1,r);
      tree2[x0][x].min:=min(tree2[x0][x<<1].min,tree2[x0][x<<1+1].min);
      tree2[x0][x].max:=max(tree2[x0][x<<1].max,tree2[x0][x<<1+1].max);
    end;
    
    procedure buildbig(x,l,r:longint);
    var
      mid:longint;
    begin
      tree1[x].left:=l;
      tree1[x].right:=r;
      if l=r then
        buildsmall(x,1,1,m)
      else begin
        mid:=(l+r)>>1;
        buildbig(x<<1,l,mid);
        buildbig(x<<1+1,mid+1,r);
        buildsmall(x,1,1,m);
      end;
    end;
    
    procedure querysmall(x0,x,l,r:longint);
    var
      mid:longint;
    begin
      if (tree2[x0][x].left=l) and (tree2[x0][x].right=r) then begin
        ansmin:=min(ansmin,tree2[x0][x].min);
        ansmax:=max(ansmax,tree2[x0][x].max);
        exit;
      end;
      mid:=(tree2[x0][x].left+tree2[x0][x].right)>>1;
      if l>mid then querysmall(x0,x<<1+1,l,r)
        else
          if r<=mid then querysmall(x0,x<<1,l,r)
          else begin
            querysmall(x0,x<<1,l,mid);
            querysmall(x0,x<<1+1,mid+1,r);
          end;
    end;
    
    procedure querybig(x,l,r:longint);
    var
      mid:longint;
    begin
      if (tree1[x].left=l) and (tree1[x].right=r) then begin
        querysmall(x,1,y1,y2);
        exit;
      end;
      mid:=(tree1[x].left+tree1[x].right)>>1;
      if l>mid then querybig(x<<1+1,l,r)
        else
          if r<=mid then querybig(x<<1,l,r)
          else begin
            querybig(x<<1,l,mid);
            querybig(x<<1+1,mid+1,r);
          end;
    end;
    
    procedure changesmall(x0,x:longint);
    var
      mid:longint;
    begin
      if tree2[x0][x].left=tree2[x0][x].right then begin
        if tree1[x0].left=tree1[x0].right then begin
          tree2[x0][x].min:=a[tree1[x0].left][tree2[x0][x].left];
          tree2[x0][x].max:=tree2[x0][x].min;
        end
        else begin
          tree2[x0][x].min:=min(tree2[x0<<1][x].min,tree2[x0<<1+1][x].min);
          tree2[x0][x].max:=max(tree2[x0<<1][x].max,tree2[x0<<1+1][x].max);
        end;
        exit;
      end;
      mid:=(tree2[x0][x].left+tree2[x0][x].right)>>1;
      if y1<=mid then changesmall(x0,x<<1)
        else changesmall(x0,x<<1+1);
      tree2[x0][x].min:=min(tree2[x0][x<<1].min,tree2[x0][x<<1+1].min);
      tree2[x0][x].max:=max(tree2[x0][x<<1].max,tree2[x0][x<<1+1].max);
    end;
    
    procedure changebig(x:longint);
    var
      mid:longint;
    begin
      if tree1[x].left=tree1[x].right then begin
        changesmall(x,1);
        exit;
      end;
      mid:=(tree1[x].left+tree1[x].right)>>1;
      if x1<=mid then changebig(x<<1)
        else changebig(x<<1+1);
      changesmall(x,1);
    end;
    
    procedure into;
    var
      i,j:longint;
    begin
      readln(n,m);
      for i:=1 to n do
        for j:=1 to m do
          read(a[i,j]);
      readln;
      buildbig(1,1,n);
    end;
    
    procedure work;
    var
      q:longint;
      ch:char;
    begin
      readln(q);
      while q>0 do begin
        dec(q);
        read(ch);
        if ch='q' then begin
          readln(x1,y1,x2,y2);
          ansmax:=-maxlongint;
          ansmin:=maxlongint;
          querybig(1,x1,x2);
          writeln(ansmax,' ',ansmin);
        end
        else begin
          readln(x1,y1,a[x1,y1]);
          changebig(1);
        end;
      end;
    end;
    
    begin
      into;
      work;
      readln;
      readln
    end.
    View Code

    (为什么我的sb线段树要记录left和right&……算了都习惯了就不改了)

    脑洞大想写二维线段树区间修改加区间查询(结果不会问了iwtwiioi大神还是不会,是不是没救了)

    云说是写不出的……

  • 相关阅读:
    HTML5+php图片自由裁剪上传功能
    一个日期时间显示框的美化风格示例
    PHP+jquery 瀑布流+LightBox图片盒子特效
    类型
    异常语句
    穷举
    练习
    累加求和
    猜拳游戏(三局两胜)
    正则表达式
  • 原文地址:https://www.cnblogs.com/Macaulish/p/4296746.html
Copyright © 2020-2023  润新知