桌子上零散地放著若干個不同顏色的盒子,桌子的後方是一堵牆。如右圖所示。問從桌子前方可以看到多少個盒子?假設人站得足夠遠(輸入時,由底向上,從左到右)。
可以把每個盒子看成一種顏色的線段,後塗的線段可以覆蓋前面的,原來的顏色為0,問最後這條直線上有多少種顏色的線段
原先構造線段樹的方法不再適用,但是我們可以通過修改線段樹的cover域的定義,使得這道題也能用線段樹來解。
定義cover如下:cover=-1表示該區間由多種顏色組成。cover>=0表示該區間只有一種單一的顏色cover。
在插入時要注意,因為在乙個大區間裡可能存在顏色不同的小區間,所以每乙個區間(顏色不為-1)在往下遞迴前,都要把左兒子和右兒子賦值成這個區間的顏色,自己賦為-1
最後統計
時間複雜度o(m log n)
type
bec=record
b,e:longint;
c:longint;
end;
var t:array[1..300000]of bec;
f:array[0..100000]of longint;
n,m,i,j,k,ans:longint;
procedure
setup
(p:longint);
var m:longint;
begin
if t[p].e-t[p].b>1
then
begin
m:=(t[p].e+t[p].b) div
2; t[p*2].b:=t[p].b;
t[p*2].e:=m;
t[p*2+1].b:=m;
t[p*2+1].e:=t[p].e;
setup(p*2);
setup(p*2+1);
end;
end;
procedure
insert
(p,l,r,i:longint);
var m:longint;
begin
if t[p].c<>i then
begin
m:=(t[p].b+t[p].e) div
2; if (l=t[p].b)and(r=t[p].e) then t[p].c:=i else
begin
if t[p].c>=0
then
begin
t[p*2].c:=t[p].c;t[p*2+1].c:=t[p].c;
t[p].c:=-1;
end;
if l>=m then insert(p*2+1,l,r,i) else
if r<=m then insert(p*2,l,r,i) else
begin
insert(p*2,l,m,i);
insert(p*2+1,m,r,i);
end;
end;
end;
end;
procedure
count
(p:longint);
begin
if t[p].c>=0
then f[t[p].c]:=1
else
if t[p].e-t[p].b>1
then
begin
count(p*2);count(p*2+1);
end;
end;
begin
readln(n);
readln(m);
t[1].b:=1;t[1].e:=n;
setup(1);
for i:=1
to m do
begin
readln(j,k);
insert(1,j,k,i);
end;
count(1);
for i:=1
to m do
if f[i]=1
then inc(ans);
writeln(ans);
end.
SSL P2645 線段樹練習題二
題目大意 n長度的桌子上零散地放著m個不同顏色的盒子,桌子的後方是一堵牆。給出每個箱子的左端跟右端,問從桌子前方可以看到多少個盒子?假設人站得足夠遠 輸入時,由底向上,從左到右 1 n 100000,1 m 100000,保證座標 l,r 範圍為 1,n 題解 線段樹 跟zju的那道題一樣,不過把記...
SSLGZ 2645 線段樹練習題二
問題描述 桌子上零散地放著若干個不同顏色的盒子,桌子的後方是一堵牆。如右圖所示。問從桌子前方可以看到多少個盒子?假設人站得足夠遠 輸入時,由底向上,從左到右 樣例輸入 16 桌子長度 5 盒子數量 4 7 12 14 1 5 6 10 11 16 樣例輸出 4演算法討論 構建線段樹,我們定義區間標記...
ssl2645 線段樹練習題2 線段樹變式
桌子上零散地放著若干個不同顏色的盒子,桌子的後方是一堵牆。如右圖所示。問從桌子前方可以看到多少個盒子?假設人站得足夠遠 輸入時,由底向上,從左到右 16 桌子長度 5 盒子數量47 121415 610111641 n 100000,1 m 100000,保證座標範圍為 1,n 可以這樣來看這道題 ...