• poj3468,poj2528


    其实这两题都是基础的线段树,但对于我这个线段树的初学者来说,总结一下还是很有用的;

    poj3468显然是线段树区间求和,区间更改的问题,而poj2528是对区间染色,问有多少种颜色的问题;

    线段树的建立和求和附代码,还是比较简单的;

    这里想说的是区间修改,用到了了lazy思想:打标记;

    拿poj2528举例,比如对区间[l,r]染色,我们只要在线段树中,被[l,r]覆盖的最大子区间[p,q]上标记被染成了什么颜色即可,不需要再往下遍历[p,q]的左右孩子;当下次修改影响到了区间[p,q]时(区间有交集),说明[p,q]一定不会全都维持原来的颜色。我们将标记向下传递给左右孩子(同时自身标记清除),不断传递下去,直至某个区间完全被要修改区间覆盖,,再给这个区间打上新的标记。这样可保证时间复杂度为O(logn);

    总之lazy思想的精髓就是,能不往下访问就不访问,要更改的时候再将子节点更改,从而减少时间复杂度;

     1 var lazy,tree:array[0..400000] of int64;
     2     l,n,m,j,x,a,b,i:longint;
     3     ans:int64;
     4     c:char;
     5 procedure pushdown(l,r,i:longint);
     6   var m:longint;
     7   begin
     8     m:=(l+r) div 2;
     9     if lazy[i]=0 then exit;
    10     lazy[i*2]:=lazy[i*2]+lazy[i];
    11     lazy[i*2+1]:=lazy[i*2+1]+lazy[i];
    12     tree[i*2]:=tree[i*2]+lazy[i]*(m-l+1);
    13     tree[i*2+1]:=tree[i*2+1]+lazy[i]*(r-m);
    14     lazy[i]:=0;
    15   end;
    16 
    17 procedure build(i,l,r:longint);
    18   var m:longint;
    19   begin
    20     if l=r then read(tree[i])
    21     else begin
    22       m:=(l+r) div 2;
    23       build(i*2,l,m);
    24       build(2*i+1,m+1,r);
    25       tree[i]:=tree[2*i]+tree[2*i+1];
    26     end;
    27   end;
    28 
    29 function find(i,l,r,l1,r1:longint):int64;
    30   var m:longint;
    31       t:int64;
    32   begin
    33     if (l>=l1) and (r<=r1) then exit(tree[i])
    34     else begin
    35       pushdown(l,r,i);
    36       m:=(l+r) div 2;
    37       t:=0;
    38       if l1<=m then t:=t+find(2*i,l,m,l1,r1);
    39       if r1>m then t:=t+find(2*i+1,m+1,r,l1,r1);
    40       exit(t);
    41     end;
    42   end;
    43 
    44 procedure work(i,l,r,l1,r1,x:longint);
    45   var m:longint;
    46   begin
    47     if (l1<=l) and (r<=r1) then
    48     begin
    49       lazy[i]:=lazy[i]+x;
    50       tree[i]:=tree[i]+(r-l+1)*x;
    51     end
    52     else begin
    53       pushdown(l,r,i);
    54       m:=(l+r) div 2;
    55       if (l1<=m) then work(i*2,l,m,l1,r1,x);
    56       if (r1>m) then work(i*2+1,m+1,r,l1,r1,x);
    57       tree[i]:=tree[i*2]+tree[i*2+1];
    58     end;
    59   end;
    60 
    61 
    62 begin
    63   readln(n,m);
    64   build(1,1,n);
    65   readln;
    66   fillchar(lazy,sizeof(lazy),0);
    67   for i:=1 to m do
    68   begin
    69     read(c);
    70     if c='Q' then
    71     begin
    72       read(a,b);
    73       ans:=find(1,1,n,a,b);
    74       writeln(ans);
    75     end
    76     else if c='C' then
    77     begin
    78       read(a,b,j);
    79       work(1,1,n,a,b,j);
    80     end;
    81     readln;
    82   end;
    83 end.
    poj3468

    而poj2528还要复杂一点,简单的建立线段树会爆空间,这需要我们把出现的区间离散化,减小空间复杂度。

      1 var tree:array[0..80000] of integer;
      2     x,y:array[0..10010] of longint;
      3     a:array[0..20010] of longint;         //表示离散化乎的标号对应的区间
      4     f:array[0..10000000] of boolean;
      5     ff:array[0..10010] of boolean;
      6     i,j,k,n,t,s:longint;
      7 procedure sort(l,r: longint);
      8   var i,j,x,y: longint;
      9   begin
     10     i:=l;
     11     j:=r;
     12     x:=a[(l+r) div 2];
     13     repeat
     14       while a[i]<x do inc(i);
     15       while x<a[j] do dec(j);
     16       if not(i>j) then
     17       begin
     18         y:=a[i];
     19         a[i]:=a[j];
     20         a[j]:=y;
     21         inc(i);
     22         j:=j-1;
     23       end;
     24     until i>j;
     25     if l<j then sort(l,j);
     26     if i<r then sort(i,r);
     27   end;
     28 procedure putdown(i,p,q:longint);         //传递标记
     29   begin
     30     if p<>q then
     31     begin
     32       tree[i*2]:=tree[i];
     33       tree[i*2+1]:=tree[i];
     34       tree[i]:=0;
     35     end;
     36   end;
     37 procedure build(i,p,q,l,r,x:longint);
     38   var m:longint;
     39   begin
     40     if (a[p]>=l) and (r>=a[q]) then tree[i]:=x
     41     else begin
     42       if tree[i]<>0 then putdown(i,p,q);
     43       m:=(p+q) div 2;
     44       if l<=a[m] then
     45       begin
     46         build(i*2,p,m,l,r,x);
     47       end;
     48       if r>a[m] then
     49       begin
     50         build(i*2+1,m+1,q,l,r,x);
     51       end;
     52     end;
     53   end;
     54 procedure dfs(i,p,q:longint);              //统计多少可见海报
     55   var m:longint;
     56   begin
     57     if (tree[i]>0) and not ff[tree[i]] then
     58     begin
     59       s:=s+1;
     60       ff[tree[i]]:=true;
     61     end
     62     else if (tree[i]=0) and (p<>q) then
     63     begin
     64       m:=(p+q) div 2;
     65       dfs(i*2,p,m);
     66       dfs(i*2+1,m+1,q);
     67     end;
     68   end;
     69 begin
     70   readln(t);
     71   for i:=1 to t do
     72   begin
     73     k:=0;
     74     fillchar(f,sizeof(f),false);
     75     readln(n);                        
     76     for j:=1 to n do 
     77     begin
     78       readln(x[j],y[j]);
     79       if not f[x[j]] then                        //离散化
     80       begin
     81         k:=k+1;
     82         a[k]:=x[j];
     83         f[x[j]]:=true;
     84       end;
     85       if not f[y[j]] then
     86       begin
     87         k:=k+1;
     88         a[k]:=y[j];
     89         f[y[j]]:=true;
     90       end;
     91     end;
     92     sort(1,k);
     93     fillchar(tree,sizeof(tree),0);
     94     for j:=1 to n do                     
     95       build(1,1,k,x[j],y[j],j);
     96     s:=0;
     97     fillchar(ff,sizeof(ff),false);
     98     dfs(1,1,k);
     99     writeln(s);
    100   end;
    101 end.
    poj2528
  • 相关阅读:
    设置表单输入框中的提示信息
    动感图文轮显
    jquery插件之图片轮显(一)整理2011.02.24
    用sort()方法对数组的元素进行排序(可按字母升序降序与获得最大最小值)
    jquery插件之图片轮显(一)
    jquery插件之图片show and hide(一)
    Pdftk The PDF Toolkit
    error while loading shared libraries: libxcbaux.so.0: cannot open shared object file
    害人的RestoreDirectory
    Oracle CASE WHEN 用法介绍
  • 原文地址:https://www.cnblogs.com/phile/p/4473313.html
Copyright © 2020-2023  润新知