乙個 \(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...