题目大意:在二维坐标系的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; }
时间: 2024-11-13 09:39:41