题意给出三种操作1.add x y将点(x,y)加入坐标系,2.remove x y将x y移出坐标系,3.find x y找到坐标系中在(x,y)的右上方且最近的点。
我们首先记录下每一步操作,进行离线处理。将横坐标进行离散化,这样的话我们可以利用lower_bound找到x对应离散化后的位置pos,对于每一个位置pos我们建立一个set,add操作时,我们将set中加入y即x[pos].insert(y),对于remove操作,我们将set中除去y即x[pos].erase(y),每次进行操作,我们利用线段树来维护这个区间上y的最大值。
对于每一个find操作,我们在pos+1到线段树的上限这个区间中寻找,如果能够找到这样的一个x我们可以利用upper_bound求出对应的y,问题解决。详细见代码。
#include <set>
#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
struct node
{
char ch[20];
int x,y;
};
node a[200005];
int n,m;
int lisan[200005];
int maxy[1000005];
set<int>x[200005];
void build(int l,int r,int k)
{
maxy[k]=-1;
if (l==r) return;
int mid=(l+r)>>1;
build(l,mid,2*k);
build(mid+1,r,2*k+1);
}
void updata(int l,int r,int k,int pos)
{
if (l==r)
{
if (x[pos].size()) maxy[k]=*(--x[pos].end());
else maxy[k]=-1;
return;
}
int mid=(l+r)>>1;
if (pos>mid) updata(mid+1,r,2*k+1,pos);
else updata(l,mid,2*k,pos);
maxy[k]=max(maxy[2*k],maxy[2*k+1]);
}
int work(int l,int r,int k,int L,int R,int VAL)
{
if ((maxy[k]<=VAL)||(L>R)) return -1; //L>R即pos是最后一个值,pos+1就大于m-1;
if (l==r) return l;
int mid=(l+r)>>1;
if (R<=mid) return work(l,mid,2*k,L,R,VAL);
else if(L>mid) return work(mid+1,r,2*k+1,L,R,VAL);
else
{
int t=work(l,mid,2*k,L,mid,VAL);
if (t!=-1) return t;
else return work(mid+1,r,2*k+1,mid+1,R,VAL);
}
}
int main()
{
scanf("%d",&n);
for (int i=0;i<n;i++)
{
scanf("%s%d%d",a[i].ch,&a[i].x,&a[i].y);
lisan[i]=a[i].x;
}
sort(lisan,lisan+n);
m=unique(lisan,lisan+n)-lisan;
build(0,m-1,1);
for (int i=0;i<m;i++) x[i].clear();
for (int i=0;i<n;i++)
{
int pos=lower_bound(lisan,lisan+m,a[i].x)-lisan;
if (a[i].ch[0]=='a')
{
x[pos].insert(a[i].y);
updata(0,m-1,1,pos);
}
else
{
if (a[i].ch[0]=='r')
{
x[pos].erase(a[i].y);
updata(0,m-1,1,pos);
}
else
{
int ans=work(0,m-1,1,pos+1,m-1,a[i].y);
if (ans==-1) printf("-1\n");
else printf("%d %d\n",lisan[ans],(*x[ans].upper_bound(a[i].y)));
}
}
}
return 0;
}