SCOI2015 國旗計畫

2021-09-01 02:18:25 字數 1914 閱讀 2456

演算法難度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 這段區間這個給定的區間是必須選擇的,於是我們...