题目大意:在二维坐标系的x正半轴,y正半轴和第一象限内,有三种操作:
1、add x,y (添加点<x,y>);
2、remove x,y(移除点<x,y>);
3、find x,y(查找在点<x,y>的绝对右上角的第一个点);
并且,只能移除已添加的点,一个点在移除之前不能重复添加。
题目分析:将横坐标离散化,线段树的每个叶子节点维护对应横坐标上的最大纵坐标。非叶子节点维护对应区间内的最大纵坐标。
代码如下:
# include<cstdio>
# include<algorithm>
# include<map>
# include<set>
# include<iostream>
using namespace std;
# define mid (l+(r-l)/2) const int N=200000; set<int>s[N+5];
char cd[N+5];
int a[N+5],b[N+5];
char str[7];
int x[N+5];
int tr[N*4+5]; void pushUp(int rt)
{
tr[rt]=max(tr[rt<<1],tr[rt<<1|1]);
} void build(int rt,int l,int r)
{
tr[rt]=-1;
if(l==r) return ;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
} void update(int rt,int l,int r,int x)
{
if(l==r){
if(s[l].empty()) tr[rt]=-1;
else tr[rt]=*(--s[l].end());
}else{
if(x<=mid) update(rt<<1,l,mid,x);
else update(rt<<1|1,mid+1,r,x);
pushUp(rt);
}
} int query(int rt,int l,int r,int x,int val)
{
if(tr[rt]<=val) return -1;
if(l==r){
return l;
}else{
if(x<=mid){
int k=query(rt<<1,l,mid,x,val);
if(k!=-1) return k;
}
return query(rt<<1|1,mid+1,r,x,val);
}
} int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=0;i<n;++i){
scanf("%s%d%d",str,a+i,b+i);
cd[i]=str[0];
x[i]=a[i];
}
sort(x,x+n);
int m=unique(x,x+n)-x;
for(int i=0;i<=m;++i)
s[i].clear(); for(int i=0;i<n;++i){
int pos=lower_bound(x,x+m,a[i])-x;
if(cd[i]=='a'){
s[pos].insert(b[i]);
update(1,0,m,pos);
}else if(cd[i]=='r'){
s[pos].erase(b[i]);
update(1,0,m,pos);
}else{
int l=query(1,0,m,pos+1,b[i]);
if(l==-1) printf("-1\n");
else{
///int r=*upper_bound(s[l].begin(),s[l].end(),b[i]);
int r=*s[l].upper_bound(b[i]); ///如果改成上面的就超时了。
printf("%d %d\n",x[l],r);
}
}
}
}
return 0;
}