1. 程式人生 > >bzoj 1178 [Apio2009]CONVENTION會議中心

bzoj 1178 [Apio2009]CONVENTION會議中心

color 如何實現 ont 相交 ret printf operator div 坐標軸

這題好難啊! 我好菜啊!

思路:對於最多線段不相交, 我們可以按左端點sort之後,貪心取。 但是這個題要求選取的線段排序之後序號的字典序最小。

那麽我們如果按序號貪心地從大往小往裏放, 那麽對於第k個線段,我們考慮放進去之後是能是還能保證所取的線段個數能

達到最大, 我們考慮函數cal(l, r) 表示坐標軸上l 到 r 最多能選取多少線段,第k條線段的左右端點是l, r, 它左邊第一條是l1, r1

它右邊第一條是l2, r2, 那麽k能放進去的充分必要條件就是cal(r1 + 1, l2 - 1) == cal(r1 + 1, l - 1) + cal(r + 1, l2 - 1) + 1。

那麽我們的問題就變成了cal()這個函數如何實現,我們將原來的線段按右端點排序之後,把包含其他線段的線段全部刪掉,

然後nx[ i ][ 0 ] = k 表示 k是第一個滿足b[k].l > b[i].r 的線段, 然後我們再倍增一下,求出nx[ i ][ j ]表示 i 右邊第2^j 個線段是誰。

 1 #include<bits/stdc++.h>
 2 #define LL long long
 3 #define fi first
 4 #define se second
 5 #define mk make_pair
 6 #define pii pair<int,int>
 7
#define piii pair<int, pair<int,int>> 8 9 using namespace std; 10 11 const int N=200000+7; 12 const int M=1e4+7; 13 const int inf=0x3f3f3f3f; 14 const LL INF=0x3f3f3f3f3f3f3f3f; 15 const int mod=1e9 + 7; 16 17 int n, m, nx[N][21], L[N], R[N]; 18 19 struct Line { 20 int l, r;
21 22 Line(int _l = 0, int _r = 0) { 23 l = _l; 24 r = _r; 25 } 26 bool operator < (const Line &rhs) const { 27 if(r == rhs.r) return l < rhs.l; 28 return r < rhs.r; 29 } 30 31 } a[N], b[N]; 32 33 int cal(int l, int r) { 34 int x = lower_bound(L + 1, L + 1 + m, l) - L; 35 if(x > m || R[x] > r) return 0; 36 int ans = 1; 37 for(int i = 20; i >= 0; i--) { 38 if(nx[x][i] && R[nx[x][i]] <= r) { 39 ans += 1 << i; 40 x = nx[x][i]; 41 } 42 } 43 return ans; 44 } 45 int main() { 46 47 scanf("%d", &n); 48 for(int i = 1; i <= n; i++) { 49 scanf("%d%d", &a[i].l, &a[i].r); 50 b[i] = a[i]; 51 } 52 53 sort(b + 1, b + n + 1); 54 55 for(int i = 1; i <= n; i++) { 56 if(!m || b[i].l > b[m].l) 57 b[++m] = b[i]; 58 } 59 60 for(int i = 1; i <= m; i++) 61 L[i] = b[i].l, R[i] = b[i].r; 62 63 for(int i = 1, j = 1; i <= m; i++) { 64 while(j <= m && b[j].l <= b[i].r) j++; 65 if(j <= m) nx[i][0] = j; 66 } 67 68 for(int i = 1; i <= 20; i++) { 69 for(int j = 1; j <= m; j++) { 70 nx[j][i] = nx[nx[j][i - 1]][i - 1]; 71 } 72 } 73 74 int ans = cal(-inf, inf); 75 printf("%d\n", ans); 76 set<Line> st; 77 int cnt = 0; 78 st.insert(Line(inf, inf)); 79 st.insert(Line(-inf, -inf)); 80 81 for(int i = 1; i <= n; i++) { 82 set<Line>::iterator it = st.lower_bound(a[i]), itt = it; itt--; 83 int l1 = itt -> r, r1 = a[i].l, l2 = a[i].r, r2 = it -> l; 84 if(l1 >= r1 || l2 >= r2) continue; 85 if(cal(l1 + 1, r2 - 1) == cal(l1 + 1, r1 - 1) + cal(l2 + 1, r2 - 1) + 1) { 86 if(++cnt == ans) printf("%d", i); 87 else printf("%d ", i); 88 st.insert(a[i]); 89 } 90 } 91 puts(""); 92 return 0; 93 } 94 /* 95 */

bzoj 1178 [Apio2009]CONVENTION會議中心