题目描述:
一个二维平面,有三个操作
Add X Y 添加 坐标为 X Y 的点
Remove X Y 删除坐标为 X Y 的点
Find X Y 寻找 X Y 右上第一个点
题目分析:
离散化 X坐标
线段树套Set,同时维护一个最大值,方便优化查询过程
题目链接:
代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <set>
using namespace std;
const int maxm=2e5+100;
int _hash[maxm];
int n,m,cnt,tot;
char s[20];
struct Point{
int x,y;
};
struct node{
int opt,x,y;
}ask[maxm];
struct tree{
std::set <int> tag[maxm];
int maxi[maxm*4];
void init(){memset(maxi,-1,sizeof(maxi));}
void pushup(int o){maxi[o]=std::max(maxi[(o<<1)],maxi[(o<<1)|1]);}
void insert(int o,int l,int r,int ind,int y)
{
if(l>=r)
{
tag[ind].insert(y);
maxi[o]=*(--tag[ind].end());
return;
}
int mid=(l+r)>>1;
ind<=mid?insert((o<<1),l,mid,ind,y):insert((o<<1)|1,mid+1,r,ind,y);
pushup(o);
}
void remove(int o,int l,int r,int ind,int y)
{
if(l>=r)
{
tag[ind].erase(y);
maxi[o]=tag[ind].empty()?-1:*(--tag[ind].end());
return;
}
int mid=(l+r)>>1;
ind<=mid?remove((o<<1),l,mid,ind,y):remove((o<<1)|1,mid+1,r,ind,y);
pushup(o);
}
Point ask(int o,int l,int r,int ind,int y)
{
if((r<ind)||(maxi[o]<y)) return Point{-1,-1};
if(l>=r) return Point{l,*(tag[l].lower_bound(y))};
int mid=(l+r)>>1;
Point P1=ask((o<<1),l,mid,ind,y);
if(P1.x!=-1) return P1;
return ask((o<<1)|1,mid+1,r,ind,y);
}
};
tree st;
int main()
{
st.init();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s%d%d",s,&ask[i].x,&ask[i].y);
_hash[++cnt]=ask[i].x;
if(s[0]=='a') ask[i].opt=1;
if(s[0]=='r') ask[i].opt=2;
if(s[0]=='f') ask[i].opt=3;
}
std::sort(_hash+1,_hash+cnt+1);
tot=std::unique(_hash+1,_hash+cnt+1)-_hash-1;
for(int i=1;i<=n;i++)
{
Point ans;
int x=lower_bound(_hash+1,_hash+tot+1,ask[i].x)-_hash;
if(ask[i].opt==1) st.insert(1,1,tot,x,ask[i].y);
if(ask[i].opt==2) st.remove(1,1,tot,x,ask[i].y);
if(ask[i].opt==3)
{
ans=st.ask(1,1,tot,x+1,ask[i].y+1);
if(ans.x==-1) printf("%d\n",-1);
else printf("%d %d\n",_hash[ans.x],ans.y);
}
}
return 0;
}