线段树成段更新+区间最值。
注意某人的乘车区间是[a, b-1],因为他在b站就下车了。
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 #define lc rt << 1 #define rc rt << 1 | 1 using namespace std; const int MAXN = 1000100; struct node { int l, r; }; node D[MAXN]; int limit, Q; int maxi[ MAXN << 2 ]; int lazy[ MAXN << 2 ]; int N; void build( int l, int r, int rt ) { maxi[rt] = lazy[rt] = 0; if ( l == r ) return; int m = ( l + r ) >> 1; build( lson ); build( rson ); return; } void PushUp( int rt ) { maxi[rt] = max( maxi[lc], maxi[rc] ); return; } void PushDown( int rt ) { if ( lazy[rt] ) { lazy[lc] += lazy[rt]; lazy[rc] += lazy[rt]; maxi[lc] += lazy[rt]; maxi[rc] += lazy[rt]; lazy[rt] = 0; } return; } void update( int L, int R, int l, int r, int rt ) { if ( L <= l && r <= R ) { lazy[rt] += 1; maxi[rt] += 1; return; } PushDown( rt ); int m = ( l + r ) >> 1; if ( L <= m ) update( L, R, lson ); if ( R > m ) update( L, R, rson ); PushUp( rt ); return; } int query( int L, int R, int l, int r, int rt ) { if ( L <= l && r <= R ) { return maxi[rt]; } PushDown( rt ); int m = ( l + r ) >> 1; int res = -10; if ( L <= m ) res = max( res, query( L, R, lson ) ); if ( R > m ) res = max( res, query( L, R, rson ) ); PushUp( rt ); return res; } int main() { int T, cas = 0; scanf( "%d", &T ); while ( T-- ) { scanf( "%d%d", &limit, &Q ); N = 0; for ( int i = 0; i < Q; ++i ) { int u, v; scanf( "%d%d", &u, &v ); N = max( N, v ); --v; D[i].l = u, D[i].r = v; } build( 1, N, 1 ); printf( "Case %d: ", ++cas ); for ( int i = 0; i < Q; ++i ) { int ans = query( D[i].l, D[i].r, 1, N, 1 ); if ( ans < limit ) { printf( "%d ", i + 1 ); update( D[i].l, D[i].r, 1, N, 1 ); } } puts(" "); } return 0; }