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
原文地址:https://www.cnblogs.com/phile/p/4473313.html