Codeforces Beta Round #19 D. Points 【线段树、set】

题目链接

题意

在坐标系中有三种操作

  1. 增加一个点 ( x , y ) (x,y) (x,y)
  2. 删除点 ( x , y ) (x,y) (x,y)
  3. 查询严格在点 ( x , y ) (x,y) (x,y) 右上角的点中,横坐标最小的点,如果有多个点,选择纵坐标最小的那个

题解

先把坐标离散化, s e t [ x ] set[x] set[x] 维护横坐标 x x x 上的点,线段树维护 x x x 轴上区间内最高的 y y y 坐标

#include<iostream>
#include<sstream>
#include<string>
#include<queue>
#include<map>
#include<unordered_map>
#include<set>
#include<vector>
#include<stack>
#include <utility>
#include<list>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<time.h>
#include<random>
using namespace std;
#include<ext/pb_ds/priority_queue.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
#include<ext/rope>
using namespace __gnu_cxx;

#define int long long
#define PI acos(-1.0)
#define eps 1e-9
#define lowbit(a) ((a)&-(a))

const int mod = 1e9+7;
int qpow(int a,int b){
	int ans=1;
	while(b){
		if(b&1)ans=(ans*a)%mod;
		a=(a*a)%mod;
		b>>=1;
	}
	return ans;
}
const int INF = 0x3f3f3f3f;
const int N = 1e6+10;
struct point{
	string op;
	int x,y;
}p[N];
struct node{
	int l,r,mid;
	int w;
}seg[N];
int lx[N],ly[N],posx,posy;
set<int>s[N];
void pu(int rt){seg[rt].w=max(seg[rt<<1].w,seg[rt<<1|1].w);}
void build(int rt,int l,int r){
	int mid=(l+r)>>1;
	seg[rt]={l,r,mid,0};
	if(l==r){seg[rt].w=-1;s[l].insert(-1);return;}
	build(rt<<1,l,mid),build(rt<<1|1,mid+1,r);
	pu(rt);
}
void update(int rt,int pos,int val){
	if(seg[rt].l==seg[rt].r){seg[rt].w=(*s[pos].rbegin());return;}
	if(pos<=seg[rt].mid) update(rt<<1,pos,val);
    else update(rt<<1|1,pos,val);
	pu(rt);	
	return;
}
void query(int rt,int val,int l,int r){
	if(l>seg[rt].r||r<seg[rt].l)return;
	if(seg[rt].w<=val||seg[rt].l>posx)return;
	if(seg[rt].l==seg[rt].r){
		if(seg[rt].w>val){
			posx=min(seg[rt].l,posx);
		}
		return;
	}
    if(seg[rt].mid>=l)query(rt<<1,val,l,r);
    if(seg[rt].mid<r)query(rt<<1|1,val,l,r);
    return;
}
#define endl '\n'
signed main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int n; cin>>n;
	for(int i=1;i<=n;i++){
		cin>>p[i].op>>p[i].x>>p[i].y;
		lx[i]=p[i].x,ly[i]=p[i].y;
	}
	sort(lx+1,lx+1+n); sort(ly+1,ly+1+n);
	int cx=unique(lx+1,lx+1+n)-lx-1,cy=unique(ly+1,ly+1+n)-ly-1;
	build(1,1,cx);
	for(int i=1;i<=n;i++){
		int px=lower_bound(lx+1,lx+1+cx,p[i].x)-lx,py=lower_bound(ly+1,ly+1+cy,p[i].y)-ly;
		if(p[i].op=="add"){
			s[px].insert(py);
			update(1,px,py);
		}
		if(p[i].op=="remove"){
			s[px].erase(py);
			update(1,px,py);
		}
		if(p[i].op=="find"){
			posx=INF; 
			query(1,py,px+1,cx);
			if(posx==INF)cout<<-1<<endl;
			else{
				set<int>::iterator it=s[posx].upper_bound(py);
				posy=*it;
				cout<<lx[posx]<<" "<<ly[posy]<<endl;
			}
		}
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值