又来练线段树了……

poj1823题意很简单(明显的数据结构题),区间修改和统计最长连续空区间;

有了poj3468的基础,区间修改不是什么问题了,重点是求最长连续空区间;(弱弱的我纠结了好久)

在每个节点上增加3个域,lmax,rmax,maxx,分别表示从左起最长,右起最长,区间内最长,然后稍稍动点脑筋即可……

 1 type node=record
 2        lmax,rmax,maxx:longint;
 3        l,r,lazy:integer;   //lazy表示区间三种情况,-1表示区间内有人住但未满,0表示无人住,1表示全住满
 4      end;
 5 var tree:array[0..80000] of node;
 6     i,n,m,a,b,c,j:longint;
 7 procedure updata(i:longint);     //更新
 8   var p:longint;
 9   begin
10     if tree[i].lazy<>-1 then
11     begin
12       if tree[i].lazy=0 then p:=tree[i].r-tree[i].l+1 else p:=0;
13       tree[i].lmax:=p;
14       tree[i].rmax:=p;
15       tree[i].maxx:=p;
16     end
17     else begin        //看起来很繁琐,实际上仔细想想就明白了
18       tree[i].lmax:=tree[i*2].lmax;
19       if tree[i].lmax=tree[i*2].r-tree[i*2].l+1 then tree[i].lmax:=tree[i].lmax+tree[i*2+1].lmax;
20       tree[i].rmax:=tree[i*2+1].rmax;
21       if tree[i].rmax=tree[i*2+1].r-tree[i*2+1].l+1 then tree[i].rmax:=tree[i].rmax+tree[i*2].rmax;
22       p:=max(tree[i].lmax,tree[i].rmax);
23       p:=max(p,max(tree[i*2].maxx,tree[i*2+1].maxx));
24       tree[i].maxx:=max(p,tree[i*2].rmax+tree[i*2+1].lmax);
25     end;
26   end;
27 
28 procedure pushdown(i:longint);  //lazy思想,注意标记下移的时候不忘更新,因为某个子区间不一定会被访问
29   begin
30     tree[i*2].lazy:=tree[i].lazy;
31     updata(i*2);
32     tree[i*2+1].lazy:=tree[i].lazy;
33     updata(i*2+1);
34     tree[i].lazy:=-1;    //需要标记下移的时候当前区间一定不会是全满或全空(想想为什么)
35   end;
36 
37 procedure build(i,l,r:longint);  //初始化线段树
38   var m:longint;
39   begin
40     tree[i].l:=l; tree[i].r:=r;
41     tree[i].lazy:=0;
42     updata(i);
43     if l<>r then
44     begin
45       m:=(l+r) div 2;
46       build(i*2,l,m);
47       build(i*2+1,m+1,r);
48     end;
49   end;
50 
51 procedure work(i,l,r,t:longint);
52   var m:longint;
53   begin
54     if (l>=a) and (r<=b) then
55     begin
56       tree[i].lazy:=t;
57       updata(i);
58     end
59     else if l<>r then begin
60       if tree[i].lazy<>-1 then pushdown(i); 
61       m:=(l+r) div 2;
62       if (a<=m) then work(i*2,l,m,t);
63       if (b>=m+1) then work(i*2+1,m+1,r,t);
64       updata(i);   // 左右子区间访问过后更新当前区间
65     end;
66   end;
67 begin
68   readln(n,m);
69   build(1,1,n);
70   for i:=1 to m do
71   begin
72     read(c);
73     if c<>3 then
74     begin
75       readln(a,b);
76       b:=a+b-1;
77       if c=1 then work(1,1,n,1) else work(1,1,n,0);  //1代表入住,0代表退房
78     end
79     else if c=3 then writeln(tree[1].maxx);
80   end;
81 end.
poj1823

话说线段树查起来真累(难道还是我太渣了?),耗了5次才AC

poj3667在poj1823基础上多了个查找但并不难,对于当前区间,按照从左区间到右区间的优先顺序找即可,一次AC

  1 type node=record
  2        l,r,lmax,rmax,maxx:longint;
  3        lazy:integer;
  4      end;
  5 
  6 var tree:array[0..200000] of node;
  7     i,n,m,a,b,c,j,l:longint;
  8 function max(a,b:longint):longint;
  9   begin
 10     if a>b then max:=a else max:=b;
 11   end;
 12 
 13  function min(a,b:longint):longint;
 14    begin
 15      if a=0 then exit(b);
 16      if b=0 then exit(a);
 17      if a>b then exit(b) else exit(a);
 18    end;
 19 procedure updata(i:longint);
 20   var p:longint;
 21   begin
 22     if tree[i].lazy<>-1 then
 23     begin
 24       if tree[i].lazy=0 then p:=tree[i].r-tree[i].l+1 else p:=0;
 25       tree[i].lmax:=p;
 26       tree[i].rmax:=p;
 27       tree[i].maxx:=p;
 28     end
 29     else begin
 30       tree[i].lmax:=tree[i*2].lmax;
 31       if tree[i].lmax=tree[i*2].r-tree[i*2].l+1 then tree[i].lmax:=tree[i].lmax+tree[i*2+1].lmax;
 32       tree[i].rmax:=tree[i*2+1].rmax;
 33       if tree[i].rmax=tree[i*2+1].r-tree[i*2+1].l+1 then tree[i].rmax:=tree[i].rmax+tree[i*2].rmax;
 34       p:=max(tree[i].lmax,tree[i].rmax);
 35       p:=max(p,max(tree[i*2].maxx,tree[i*2+1].maxx));
 36       tree[i].maxx:=max(p,tree[i*2].rmax+tree[i*2+1].lmax);
 37     end;
 38   end;
 39 
 40 procedure pushdown(i:longint);
 41   begin
 42     tree[i*2].lazy:=tree[i].lazy;
 43     updata(i*2);
 44     tree[i*2+1].lazy:=tree[i].lazy;
 45     updata(i*2+1);
 46     tree[i].lazy:=-1;
 47   end;
 48 
 49 procedure find(i:longint);
 50   begin
 51     if tree[i].maxx<l then exit;
 52     if (tree[i].lmax>=l) then a:=tree[i].l
 53     else if tree[2*i].maxx>=l then
 54       find(2*i)
 55     else if tree[i*2].rmax+tree[i*2+1].lmax>=l  then
 56     begin
 57       a:=tree[i*2].r-tree[i*2].rmax+1;
 58     end
 59     else if tree[i*2+1].maxx>=l then find(2*i+1);
 60     if tree[i].rmax>=l then a:=min(a,tree[i].r-tree[i].rmax+1);
 61   end;
 62 
 63 procedure build(i,l,r:longint);
 64   var m:longint;
 65   begin
 66     tree[i].l:=l; tree[i].r:=r;
 67     tree[i].lazy:=0;
 68     updata(i);
 69     if l<>r then
 70     begin
 71       m:=(l+r) div 2;
 72       build(i*2,l,m);
 73       build(i*2+1,m+1,r);
 74     end;
 75   end;
 76 
 77 procedure work(i,l,r,t:longint);
 78   var m:longint;
 79   begin
 80     if (l>=a) and (r<=b) then
 81     begin
 82       tree[i].lazy:=t;
 83       updata(i);
 84     end
 85     else if l<>r then begin
 86       if tree[i].lazy<>-1 then pushdown(i);
 87       m:=(l+r) div 2;
 88       if (a<=m) then work(i*2,l,m,t);
 89       if (b>=m+1) then work(i*2+1,m+1,r,t);
 90       updata(i);
 91     end;
 92   end;
 93 
 94 begin
 95   readln(n,m);
 96   build(1,1,n);
 97   for i:=1 to m do
 98   begin
 99     read(c);
100     if c=1 then
101     begin
102       readln(l);
103       a:=0;
104       find(1);
105       writeln(a);
106       b:=a+l-1;
107       if a<>0 then work(1,1,n,1);
108     end
109     else if c=2 then
110     begin
111       readln(a,b);
112       b:=a+b-1;
113       work(1,1,n,0);
114     end;
115   end;
116 end.
poj3667

 

posted on 2013-12-14 20:05  acphile  阅读(226)  评论(0编辑  收藏  举报