又来练线段树了……
poj1823题意很简单(明显的数据结构题),区间修改和统计最长连续空区间;
有了poj3468的基础,区间修改不是什么问题了,重点是求最长连续空区间;(弱弱的我纠结了好久)
在每个节点上增加3个域,lmax,rmax,maxx,分别表示从左起最长,右起最长,区间内最长,然后稍稍动点脑筋即可……
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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.
话说线段树查起来真累(难道还是我太渣了?),耗了5次才AC
poj3667在poj1823基础上多了个查找但并不难,对于当前区间,按照从左区间到右区间的优先顺序找即可,一次AC
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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.