演算法難度5,思維難度6,**難度5
給定乙個長度為m
mm的環,環上有m
mm個點[1,
m]
[1,m]
[1,m
],以及n
nn個互不包含的區間。
要求對於每個區間求出,在必須選這個區間的前提下,能使得所有被選區間覆蓋整個環的最少區間數。
1 ≤n
≤2×1
05,m
<10
91\le n\le 2\times 10^5,m<10^9
1≤n≤2×
105,
m<10
9首先區間互不包含,那麼我們將所有區間按照左端點排序之後,區間一定滿足左端點和右端點同時嚴格遞增。
破環成鏈之後,這樣我們可以二分或者遞推求出選每個區間的下乙個最優選擇區間。
求出來之後,比如第i
ii個區間的下乙個最優區間是f(i
)f(i)
f(i)
,那麼就從f(i
)f(i)
f(i)
向i
ii連一條邊。
這樣我們倍增預處理每個點的2
j2^j
2j級祖先,查詢的時候就固定這個區間開始,限制不能再跳過這個區間的左端點,然後直接倍增跳就好了,最後加上沒有算的這兩個區間。
時間複雜度o(n
logn
)o(nlogn)
o(nlog
n)
#include
#include
#include
#include
#include
#include
#define ll long long
using
namespace std;
inline
intread()
while
(ch>=
'0'&& ch<=
'9')x=x*10+
(ch^48)
,ch=
getchar()
;return f==
1?x:
-x;}
const
int n=
4e5+5;
struct data
data
(int _l,
int _r,
int _id):l
(_l),r
(_r),id
(_id)
inline
bool
operator
<
(const data& b)
const
}a[n]
;int n,m,c[n]
,d[n]
,tot,fa[n][19
],ans[n]
;int
main()
sort
(a+1
,a+tot+1)
;for
(int i=
1;i++i)
fa[i][0
]=l;
}for
(int k=
1;k<=18;
++k)
for(
int i=
1;i<=tot;
++i)
fa[i]
[k]=fa[fa[i]
[k-1]]
[k-1];
for(
int i=
1;i<=tot;
++i)
for(
int i=
1;i<=n;
++i)
printf
("%d "
,ans[i]+2
);return0;
}
SCOI2015 國旗計畫
斷環為鏈,將環複製兩倍。用to i j 表示從點i出發,走 2 j 步能夠到達的最遠的 右端點qwq 的編號。注意為了方便判斷已經走了一圈了,我們最後一步先不要跳,只需要判斷當前右端點仍在i n之前即可。然後這個樣子的話,最後答案需要 1。如下 include include include inc...
SCOI2015 國旗計畫
bzoj luogu 先考慮破環為鏈 由於區間不包含,我們sort之後可以貪心的選左端點在當前右端點之前的最後乙個 然後預處理乙個倍增陣列,每次logn查一下 複雜度 o nlogn 空間兩倍,tot 1的r設為inf includeusing namespace std const int 4e5...
SCOI2015 國旗計畫
題目 首先考慮一下環形的區間覆蓋問題怎麼做 我們可以把環倍長成鏈,之後驚訝的發現我只會列舉乙個 i 作為起點跑 i,i m 的區間覆蓋 看起來非常垃圾,但是會這樣做就夠了 考慮列舉到的這個 i 作為乙個某乙個給定的區間的左端點的時候,想要覆蓋 i,i m 這段區間這個給定的區間是必須選擇的,於是我們...