codeForce-19D Points (点更新+离散化)

题目大意:在二维坐标系的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
");
				else{
                    ///int r=*upper_bound(s[l].begin(),s[l].end(),b[i]);
					int r=*s[l].upper_bound(b[i]);  ///如果改成上面的就超时了。
					printf("%d %d
",x[l],r);
				}
			}
		}
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/20143605--pcx/p/5583709.html