离散化贪心不多说了。然后在字典序最小上卡思路……想到了这个题要维护字典序最小的话,就应该按照顺序判断某线段可行与否。该线段[L, R]可行要满足以下两个条件:
1) 这条线段没有接触到任何一个被覆盖的点。
2) 那么这条线段一定落在一个可行区间[L', R']中。设MT(A, B)表示区间[A, B]最多能放几条线段,就必须满足MT(L', L - 1) + MT(R + 1, R') + 1 = MT(L', R')。
如果这条线段可行,那么就输出它,并且把这条线段所在的区间分断成[L', L - 1]和[R + 1, R']。
这个解决方案有这样几个问题没有解决:
首先,查找[L, R]所在区间。这个不多说,直接用平衡树。当然线段树也是可以的。
之后就是MT函数的计算。这可是这个题的精髓所在!
首先我们去掉所有包含其他线段的线段,并按照其L排序。显然这时R也是排好序的。
设RIGHT(x)为从x开始向右走,遇到的第一个区间的右边界加一(若是x右边一个可行区间都没有就返回infinite)。设M(0, x) = RIGHT(x),M(k, x) = RIGHT(M(k - 1, x))。那么,MT(L, R) = max { k | M(K, L) <= R + 1 }。对于这种问题,有一个大杀器可用,那就是倍增。我们首先要预处理一个二维数组jump,使得jump[k][x] = M(2^k, x),预处理这个数组可以用jump[0][x] = RIGHT(x),jump[k][x] = jump[k - 1][jump[k - 1][x]]来做。之后,求MT(L, R)的方法就变得简单啦:首先从高到底枚举i,0->ans,如果jump[i][L] <= R + 1,那么ans + 1<<i -> ans,jump[i][L] -> L,一直做下去直到i = 0计算完毕。这样的复杂度是O(logN)。
总体时间复杂度就是O(NlogN)。
-
#include <cstdio>
-
#include <cstring>
-
#include <cstdlib>
-
#include <vector>
-
#include <set>
-
#include <algorithm>
-
using namespace std ;
-
-
const int mi = 19931117 ;
-
int lsh [ 500020 ], lsht [ 500020 ], lshmr ;
-
void initialize ( void )
-
{
-
sort (lsh, lsh + lshmr ) ;
-
int cnt = 0 ;
-
for ( int i = 0 ; i < lshmr ; i ++ )
-
{
-
if (i == 0 || lsh [i ] ! = lsh [i - 1 ] )
-
lsht [cnt ++ ] = lsh [i ] ;
-
} lshmr = cnt ;
-
}
-
inline int place ( int a )
-
{
-
int st = 0, ed = lshmr, mid ;
-
while (ed - st > 1 )
-
{
-
mid = (st + ed ) >> 1 ;
-
if (lsht [mid ] > a ) ed = mid ;
-
else st = mid ;
-
} return st + 1 ;
-
}
-
pair < int, int > require [ 250010 ] ;
-
pair < int, int > rs [ 250010 ], trs [ 250010 ] ; int trmr ;
-
bool comp ( const pair < int, int > & a, const pair < int, int > & b )
-
{
-
if (a. first ! = b. first ) return a. first < b. first ;
-
else return a. second > b. second ;
-
}
-
-
int jump [ 20 ] [ 500010 ], maxj ;
-
void jump_st ( void )
-
{
-
int p = 0 ; jump [ 0 ] [lshmr + 1 ] = mi ;
-
for ( int i = lshmr ; i >= 1 ; i -- )
-
{
-
if (p < trmr && i == trs [p ]. first ) jump [ 0 ] [i ] = trs [p ++ ]. second + 1 ;
-
else jump [ 0 ] [i ] = jump [ 0 ] [i + 1 ] ;
-
}
-
bool valid ;
-
for ( int i = 1 ; ; i ++ )
-
{
-
valid = false ;
-
jump [i ] [lshmr + 1 ] = mi ;
-
for ( int k = 1 ; k <= lshmr ; k ++ )
-
{
-
if (jump [i - 1 ] [k ] == mi ) jump [i ] [k ] = mi ;
-
else jump [i ] [k ] = jump [i - 1 ] [jump [i - 1 ] [k ] ] ;
-
if (jump [i ] [k ] < mi ) valid = true ;
-
}
-
if (valid == false ) { maxj = i - 1 ; break ; }
-
}
-
}
-
int max_time ( int s, int e )
-
{
-
if (s >= e ) return 0 ;
-
int ts = s, ans = 0 ; ++e ;
-
for ( int j = maxj ; j >= 0 && ts < e ; j -- )
-
if (jump [j ] [ts ] <= e ) ts = jump [j ] [ts ], ans + = ( 1 << j ) ;
-
return ans ;
-
}
-
set <pair < int, int > > query ;
-
typedef set <pair < int, int > > :: iterator ptr ; int ans ;
-
bool judge ( int i )
-
{
-
int l = require [i ]. first, r = require [i ]. second ;
-
ptr t1, t2 ;
-
t1 = query. lower_bound (make_pair (l, mi ) ) ;
-
if (t1 == query. begin ( ) ) return false ; else --t1 ;
-
if (t1 - >second < l ) return false ;
-
t2 = --query. lower_bound (make_pair (r, mi ) ) ;
-
if (t1 ! = t2 ) return false ;
-
if (t1 - >second < r ) return false ;
-
int ll = t1 - >first, rr = t1 - >second ;
-
int tans = max_time (ll, l - 1 ) + max_time (r + 1, rr ) + 1 ;
-
int sans = max_time (ll, rr ) ;
-
if (tans < sans ) return false ;
-
else
-
{
-
query. erase (t1 ) ;
-
if (ll <= l - 1 ) query. insert (make_pair (ll, l - 1 ) ) ;
-
if (r + 1 <= rr ) query. insert (make_pair (r + 1, rr ) ) ;
-
return true ;
-
}
-
}
-
int main ( )
-
{
-
int n, ans ; scanf ( "%d", &n ), lshmr = 0 ;
-
for ( int i = 0 ; i < n ; i ++ )
-
{
-
scanf ( "%d %d", &require [i ]. first, &require [i ]. second ) ;
-
lsh [lshmr ++ ] = require [i ]. first ;
-
lsh [lshmr ++ ] = require [i ]. second ;
-
}
-
initialize ( ) ;
-
for ( int i = 0 ; i < n ; i ++ )
-
{
-
int l = place (require [i ]. first ), r = place (require [i ]. second ) ;
-
require [i ]. first = l, require [i ]. second = r ;
-
rs [i ] = make_pair (l, r ) ;
-
}
-
sort (rs, rs + n, comp ), trmr = 0 ; int p ;
-
for ( int i = n - 1 ; i >= 0 ; i -- )
-
{
-
if (i == n - 1 || rs [i ]. second < rs [p ]. second )
-
trs [trmr ++ ] = rs [i ], p = i ;
-
}
-
jump_st ( ) ;
-
query. insert (make_pair ( 1, lshmr ) ) ;
-
printf ( "%d\n", ans = max_time ( 1, lshmr ) ) ;
-
for ( int i = 0 ; i < n ; i ++ )
-
if (judge (i ) ) printf ( "%d ", i + 1 ) ;
-
printf ( "\n" ) ;
-
return 0 ;
-
}
-