题意:
在二维坐标平面内进行n (1 ≤ n ≤ 2·105)
次操作。一共有三种类型操作。
1.add x,y 将点(x,y)加进坐标系。
2.remove x,y 将点(x,y)移除.
3.find x,y 找到点(x,y)右上角的点(xp>x,yp>y)。如果有多个输出x最小的。还是有多个输出y最小的。
x,y均为非负数。以上操作均合法。
思路:
我们可以用N个set维护很坐标为i的y有哪些。当然需离线对x离散化。这题关键是询问有点难对付。如果我们知道find x,y操作时。最小的满足的x是多少。我们就可以在对应的set里找最小满足的y了。所以怎样快速找到x就是突破点了。我们可以用一颗线段树维护x为v时y的最大值。这样我们只要查询x比v大的区间能否满足在二分就可以快速定位最小的满足的x了。
详细见代码:
#include<bits/stdc++.h> using namespace std; const int INF=0x3f3f3f3f; const int maxn=200010; typedef long long ll; #define lson L,mid,ls #define rson mid+1,R,rs struct node { int x,y,id; char cmd[20]; void init(){ scanf("%s%d%d",cmd,&x,&y); } } q[maxn]; set<int> st[maxn]; int mav[maxn<<2],H[maxn]; int n,m; void build(int L,int R,int rt) { mav[rt]=-1; if(L==R) return; int ls=rt<<1,rs=ls|1,mid=(L+R)>>1; build(lson); build(rson); } void update(int L,int R,int rt,int p) { if(L==R) { if(st[L].size()) mav[rt]=*(--st[L].end()); else mav[rt]=-1; return; } int ls=rt<<1,rs=ls|1,mid=(L+R)>>1; if(p>mid) update(rson,p); else update(lson,p); mav[rt]=max(mav[ls],mav[rs]); } int qu(int L,int R,int rt,int l,int r,int x) { if(mav[rt]<=x||l>r) return -1; if(L==R) return L; int ls=rt<<1,rs=ls|1,mid=(L+R)>>1,tp=-1; if(l<=mid)//想想怎样才会到左子树查。 tp=qu(lson,l,r,x); if(tp!=-1) return tp; if(r>mid) return qu(rson,l,r,x); } void init() { sort(H,H+m); m=unique(H,H+m)-H; } int Hash(int x) { return lower_bound(H,H+m,x)-H; } int main() { int i,h,p; while(~scanf("%d",&n)) { m=n; for(i=0;i<n;i++) q[i].init(),H[i]=q[i].x; init(); build(1,m,1); for(i=0;i<n;i++) { h=Hash(q[i].x)+1; if(q[i].cmd[0]=='a') st[h].insert(q[i].y),update(1,m,1,h); else if(q[i].cmd[0]=='r') st[h].erase(q[i].y),update(1,m,1,h); else { p=qu(1,m,1,h+1,m,q[i].y);//m打成n调了好久。。。。 if(p==-1) printf("-1\n"); else printf("%d %d\n",H[p-1],*st[p].upper_bound(q[i].y));//upper>.lower>=的第一个 } } } return 0; }