Codeforces Beta Round #19 D. Points 线段树+set

给你一个笛卡尔坐标系,现在要支持三种操作,第一种操作是添加一个点(x,y),第二种操作是删除一个点(x,y), 第三种操作是查询严格在点(x,y)右上角的点中,横坐标最小的点,如果有多个点,选择纵坐标最小的那个。

--------

首先肯定离散化

然后考虑怎么用线段树表示二维的信息,觉得树套树也可以写,但是线段树套set更好写一点

以x为下标建立线段树,对每个叶子节点开一个set,表示x点有多少个y。

添加和查找只要递归到叶节点删去/增加就可以了

查找的话,要求严格在(x,y)右上

转化为代数也就是在(x+1,maxn)上找一个最小的下标满足该下标能顶到的最大值>y;

最小下标只要优先递归左子树就能满足;

找到后在set内upper_bound即可;

 

复制代码
#include<bits/stdc++.h>
#define ls (rt<<1)
#define rs (rt<<1|1)
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int maxn=4e5+5;
int n;
int op[maxn],x[maxn],y[maxn],lisan[maxn<<1];
struct seg{
    int l,r,mx;
}t[maxn<<2];
set<int>s[maxn<<2];
void push_up(int rt){
    t[rt].mx=max(t[ls].mx,t[rs].mx);
}
void build(int rt,int l,int r){
    t[rt].l=l;t[rt].r=r;
    if(l==r){
       t[rt].mx=-1;
       return;
    }
    int mid=(l+r)>>1;
    build(ls,l,mid);build(rs,mid+1,r);
}
void update(int rt,int l,int r,int val,int type){
    //cout<<rt<<" "<<t[rt].l<<" "<<t[rt].r<<" "<<l<<" "<<r<<" "<<val<<" "<<type<<endl;
    if(l<=t[rt].l&&t[rt].r<=r){
        // update
        if(type==0){
            s[rt].erase(val);
            if(s[rt].empty()) t[rt].mx=-1;
            else t[rt].mx=*s[rt].rbegin();
        }
        else {
            s[rt].insert(val);
            t[rt].mx=*s[rt].rbegin();
        }
        return;
    }
    if(t[ls].r>=l) update(ls,l,r,val,type);
    if(t[rs].l<=r) update(rs,l,r,val,type);
    push_up(rt);
}
int Ansx=0;
int query(int rt,int l,int r,int y){
    //cout<<":: "<<rt<<" "<<t[rt].l<<" "<<t[rt].r<<" "<<l<<" "<<r<<" "<<y<<" "<<t[rt].mx<<endl;
    if(l>r) return 0;
    if(l<=t[rt].l&&t[rt].r<=r){
        if(t[rt].mx<=y) return 0;
    }
    if(t[rt].l==t[rt].r){
        if(t[rt].mx<=y) return 0;
        else {
           Ansx=t[rt].l;
           return *s[rt].upper_bound(y);    
        }
    }
    int ans=0;
    if(t[ls].r>=l&&t[ls].mx>y) ans=query(ls,l,r,y);
    if(ans) return ans;
    if(t[rs].l<=r&&t[rs].mx>y) ans=query(rs,l,r,y);
    return ans;
}
int cnt=0;
int id(int x){
    return lower_bound(lisan+1,lisan+cnt+1,x)-lisan;
}
int main(){
    //freopen("lys.in","r",stdin);
    fastio;
    cin>>n;
    for(int i=1;i<=n;i++){
        string s;
        cin>>s;
        if(s[0]=='a') op[i]=1;
        if(s[0]=='f') op[i]=2;
        cin>>x[i]>>y[i];
        lisan[++cnt]=x[i];
        lisan[++cnt]=y[i];
    }
    sort(lisan+1,lisan+cnt+1);
    cnt=unique(lisan+1,lisan+cnt+1)-(lisan+1);
    build(1,1,cnt);
    for(int i=1;i<=n;i++){
        if(op[i]==0){
            //remove
            update(1,id(x[i]),id(x[i]),y[i],0);
        }
        else if(op[i]==1){
            //add    
            update(1,id(x[i]),id(x[i]),y[i],1);
        }
        else {
            //find
            int out=query(1,id(x[i])+1,cnt,y[i]);
            if(out==0) cout<<-1<<endl;
            else cout<<lisan[Ansx]<<" "<<out<<endl;
        }
    }
}
复制代码

 

posted @   liyishui  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示