P4155 SCOI2015 國旗計畫

2022-09-18 22:51:11 字數 1243 閱讀 7796

乙個 \(m\) 個點的環,有 \(n\) 條線段,可覆蓋在環上 \([l_i,r_i]\) 的部分,且線段不會互相包含,對 \(1\le i\le n\) 問強制選擇線段 \(i\) 時,最少選擇多少條線段可以覆蓋整個環。

保證 \(1 \leq n\le 2\times 10^5,m<10^9\)。

對於環,直接斷環為鏈,變為線段覆蓋問題。

因為線段互不包含,則按照左端點排序後右端點必然單調,那麼被線段 \(i\) 部分包含且右端點最遠的的線段 \(j\) 是固定的。

考慮計算出每個 \(i\) 的下一條線段,然後倍增求出每條線段條 \(2^k\) 步跳到的線段。

對於詢問,倍增至 \(r_j,最後答案加上 \(2\) 即可。

時間複雜度 \(\mathcal o(n \log n)\)。

#include using namespace std;

inline int read()

while(c >= '0' && c <= '9')

return x * f;

}inline void write(int x)

if(x > 9)

write(x / 10);

putchar(x % 10 + '0');

}const int _ = 2e5 + 10;

int n, m, ans[_];

int f[20][_ << 1];

struct xd

} a[_ << 1];

int main()

sort(a + 1, a + n + 1);

for (register int i = 1; i <= n; i++)

a[i + n].l = a[i].l + m, a[i + n].r = a[i].r + m;

for (register int i = 1, j = 1; i <= n << 1; i++)

for (register int i = 1; i <= 19; i++)

for (register int j = 1; j <= n << 1; j++)

f[i][j] = f[i - 1][f[i - 1][j]];

for (register int i = 1; i <= n; i++)

for (register int i = 1; i <= n; i++)

write(ans[i]), putchar(' ');

}

SCOI2015 國旗計畫

演算法難度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...

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...