線段樹+離散化。離線處理,由於查詢的時候我們需要找到所有滿足條件的結果中行最小且列最小的。我們以行建樹,然後將行對應的列中的值有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 ;
}