线段树,维护每个区间的maxy,查找时用二分。
/*Accepted 3627 1203MS 6848K 2698 B C++*/ #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN = 200010; struct TPoint{ int x, y, flag; }pre[MAXN], ans[MAXN], s; char op[10]; int n, m; struct Segtree { int l, r, maxy; }tree[MAXN << 2]; bool cmp(TPoint a, TPoint b) { return a.x < b.x || ( a.x == b.x && a.y < b.y); } void build( int rt, int l, int r) { tree[rt].l = l, tree[rt].r = r, tree[rt].maxy = -1; if( l == r) return; int m = (l + r) >> 1; build( rt << 1, l, m); build( rt << 1 | 1, m + 1, r); } int BS( TPoint nd, int l, int r) { while( l <= r){ int m = (l + r) >> 1; if( nd.x == ans[m].x && nd.y == ans[m].y) return m; if( nd.x < ans[m].x || nd.x == ans[m].x && nd.y < ans[m].y) r = m - 1; else l = m + 1; } return -1; } void update( int rt, int l, int flag) { if( tree[rt].l == l && tree[rt].r == l) { if( 1 == flag) tree[rt].maxy = ans[l].y; if( 2 == flag) tree[rt].maxy = -1; return; } int m = (tree[rt].l + tree[rt].r) >> 1; if(l <= m) update( rt << 1, l, flag); else update( rt << 1 | 1, l, flag); tree[rt].maxy = max( tree[rt << 1].maxy, tree[rt << 1 | 1].maxy); } void query(int rt, TPoint nd) { if(tree[rt].maxy <= nd.y) return; if(ans[tree[rt].r].x <= nd.x) return; if( tree[rt].l == tree[rt].r){ s = ans[tree[rt].l]; return; } query(rt << 1, nd); if(s.x == -1) query(rt << 1 | 1, nd); } void prepare() { int i; for( i = 1, m = 0; i <= n; i ++) { scanf( "%s%d%d", op, &pre[i].x, &pre[i].y); if('a' == op[0]) { pre[i].flag = 1; ans[++ m] = pre[i]; } else if( 'r' == op[0]) pre[i].flag = 2; else pre[i].flag = 3; } sort( ans + 1, ans + m + 1, cmp); build( 1, 1, m); } void operation() { for( int i = 1; i <= n; i ++) { int cnt = BS(pre[i], 1, m); if( 3 == pre[i].flag) { s.x = s.y = -1; query( 1, pre[i]); if( s.x == -1) printf( "-1\n"); else printf( "%d %d\n", s.x, s.y); } else{ update( 1, cnt, pre[i].flag); } } } int main() { int cas = 0; while( scanf( "%d", &n), n) { if( cas ++) printf( "\n"); printf( "Case %d:\n", cas); prepare(); operation(); } return 0; }