传送门:【CodeForces】19D Points
题目分析:将X轴离散化,然后构造一棵线段树,线段树的每个叶子节点维护一个set,里面为坐标为a[x]的点的y坐标的集合。线段树维护区间内所有点能达到的y的最大值。
每次插入删除就单点更新,询问的时候看区间【x+1,cnt】内maxv[ o ]是否大于y,不存在返回0,否则返回最左边满足集合内存在y坐标大于查询的值的下标。然后在下标所在的集合查询最小的大于y的y'值即可。
set真是强大!
代码如下:
#include <set> #include <cstdio> #include <cstring> #include <algorithm> using namespace std ; typedef long long LL ; #define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next ) #define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i ) #define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i ) #define FOR( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i ) #define clr( a , x ) memset ( a , x , sizeof a ) #define cpy( a , x ) memcpy ( a , x , sizeof a ) #define mid ( ( l + r ) >> 1 ) #define ls ( o << 1 ) #define rs ( o << 1 | 1 ) #define lson ls , l , m #define rson rs , m + 1 , r #define root 1 , 1 , cnt #define rt o , l , r #define mid ( ( l + r ) >> 1 ) const int MAXN = 200005 ; struct Node { int x , y ; char op ; } opp[MAXN] ; int maxv[MAXN << 2] ; int a[MAXN] , cnt ; set < int > p[MAXN] ; int n ; void update ( int pos , int o , int l , int r ) { if ( l == r ) { if ( p[pos].empty () ) maxv[o] = 0 ; else maxv[o] = *p[pos].rbegin () ;//返回end的值 return ; } int m = mid ; if ( pos <= m ) update ( pos , lson ) ; else update ( pos , rson ) ; maxv[o] = max ( maxv[ls] , maxv[rs] ) ; } int query ( int L , int R , int key , int o , int l , int r ) { if ( maxv[o] <= key ) return 0 ; if ( l == r ) return l ; int m = mid ; if ( R <= m ) return query ( L , R , key , lson ) ; if ( m < L ) return query ( L , R , key , rson ) ; int res = query ( L , R , key , lson ) ; if ( !res ) res = query ( L , R , key , rson ) ; return res ; } int unique ( int n ) { int cnt = 1 ; sort ( a + 1 , a + n + 1 ) ; FOR ( i , 2 , n ) if ( a[i] != a[cnt] ) a[++ cnt] = a[i] ; return cnt ; } int hash ( int x ) { int l = 1 , r = cnt , m ; while ( l < r ) { m = mid ; if ( a[m] >= x ) r = m ; else l = m + 1 ; } return l ; } void solve () { char buf[10] ; FOR ( i , 1 , n ) { scanf ( "%s%d%d" , buf , &opp[i].x , &opp[i].y ) ; a[i] = opp[i].x ; opp[i].op = buf[0] ; p[i].clear () ; } cnt = unique ( n ) ; FOR ( i , 1 , n ) { int x = hash ( opp[i].x ) , y = opp[i].y ; if ( opp[i].op == 'a' ) { p[x].insert ( y ) ; update ( x , root ) ; } else if ( opp[i].op == 'r' ) { p[x].erase ( y ) ; update ( x , root ) ; } else { if ( x + 1 > cnt ) x = 0 ; if ( x ) x = query ( x + 1 , cnt , y , root ) ; if ( x ) printf ( "%d %d\n" , a[x] , *p[x].upper_bound ( y ) ) ; else printf ( "-1\n" ) ; } } } int main () { while ( ~scanf ( "%d" , &n ) ) solve () ; return 0 ; }