线段树+离散化。离线处理,由于查询的时候我们需要找到所有满足条件的结果中行最小且列最小的。我们以行建树,然后将行对应的列中的值有set保存下来。首先将数据读入,然后将行从大到小进行排序,维护一个区间中的列最大的值。添加与删除操作很相似,一个是相当于将点的标记为1,另一个就是将标记置为0,所以只需要1个update函数就可以了。然后查询的时候很简单,我们只需要找到行最小的,并且满足最大的列比给定的列大的。搜列的时候直接采用set的lower_bound函数。
/*
author : csuchenan
PROG : hdu 3627
algorithm: segment tree + set
对一维进行建树,将第二维采用set存储,然后在对第二维进行查询的时候我们可以直接用lower_bound进行查询
查询复杂度为logn * logn,用set能够很快进行查询,并且写起来比较方便
*/
#include <cstdio>
#include <algorithm>
#include <set>
using namespace std ;
const int maxn = 200005 ;
struct Tree{
int l , r ;
int col ;
}tree[maxn*3] ;
struct CMD{
char op ;
int x , y ;
}cmd[maxn] ;
int linex[maxn] ;
set<int> st[maxn];
int n ;
typedef pair<int ,int> RES ;
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define M(x , y) (x + y >>1)
void build(int l , int r , int c){
tree[c].l = l ;
tree[c].r = r ;
tree[c].col = -1 ;
if(l == r){
st[l].clear() ;
return ;
}
build(l , M(l , r) , L(c)) ;
build(M(l , r) + 1, r , R(c)) ;
}
void update(int p , int op , int y , int c){
if(tree[c].l == tree[c].r){
if(op==1){
tree[c].col = max(tree[c].col , y) ;
st[p].insert(y) ;
}
else{
st[p].erase(y) ;
if(st[p].empty()){
tree[c].col = -1 ;
}
else
tree[c].col = *st[p].rbegin();
}
return ;
}
int m = M(tree[c].l , tree[c].r) ;
if(p <= m){
update(p , op , y , L(c)) ;
}
else{
update(p , op , y , R(c)) ;
}
tree[c].col = max(tree[L(c)].col , tree[R(c)].col) ;
}
RES query(int l , int r, int y , int c){
if(tree[c].col < y){
return make_pair(0 , -1) ;
}
if(tree[c].l == tree[c].r){
set<int> :: iterator it ;
it = st[tree[c].l].lower_bound(y) ;
return make_pair(tree[c].l , *it) ;
}
int m = M(tree[c].l , tree[c].r) ;
if(r <= m){
return query(l , r , y , L(c));
}
else if(l > m){
return query(l , r , y , R(c)) ;
}
else{
RES p = query(l , m , y , L(c)) ;
if(p.second != -1){
return p ;
}
return query(m + 1 , r , y , R(c)) ;
}
}
int main(){
char str[10] ;
int x , y , cas = 1;
freopen("test.in" ,"r" , stdin) ;
while(scanf("%d" , &n) , n){
for(int i = 0 ; i < n ; i ++){
scanf("%s%d%d" , str , &x , &y) ;
linex[i] = x ;
cmd[i].op = str[0] ;
cmd[i].x = x ;
cmd[i].y = y ;
}
sort(linex , linex + n) ;
int len = unique(linex , linex + n) - linex ;
build(0 , len - 1 , 1) ;
if(cas != 1)
printf("\n") ;
printf("Case %d:\n" , cas ++) ;
for(int i = 0 ; i < n ; i ++){
int pos = lower_bound(linex , linex + len , cmd[i].x) - linex ;
if(cmd[i].op == 'a'){
update(pos , 1 , cmd[i].y , 1) ;
}
else if(cmd[i].op == 'r'){
update(pos , 0 , cmd[i].y , 1) ;
}
else{
if(pos + 1 > len - 1){
printf("-1\n") ;
continue ;
}
RES t = query(pos + 1 , len - 1 , cmd[i].y + 1 , 1) ;
if(t.second == -1){
printf("-1\n") ;
}
else{
printf("%d %d\n" , linex[t.first] , t.second) ;
}
}
}
}
return 0 ;
}