CodeForces 19D 离散化+线段树+set

4 篇文章 0 订阅
2 篇文章 0 订阅

     题意给出三种操作1.add x y将点(x,y)加入坐标系,2.remove x y将x y移出坐标系,3.find x y找到坐标系中在(x,y)的右上方且最近的点。

    我们首先记录下每一步操作,进行离线处理。将横坐标进行离散化,这样的话我们可以利用lower_bound找到x对应离散化后的位置pos,对于每一个位置pos我们建立一个set,add操作时,我们将set中加入y即x[pos].insert(y),对于remove操作,我们将set中除去y即x[pos].erase(y),每次进行操作,我们利用线段树来维护这个区间上y的最大值。

   对于每一个find操作,我们在pos+1到线段树的上限这个区间中寻找,如果能够找到这样的一个x我们可以利用upper_bound求出对应的y,问题解决。详细见代码。

#include <set>
#include <cstdio>
#include <algorithm>
#include <iostream>

using namespace std;

struct node
{
    char ch[20];
    int x,y;
};
node a[200005];

int n,m;
int lisan[200005];
int maxy[1000005];
set<int>x[200005];

void build(int l,int r,int k)
{
    maxy[k]=-1;
    if (l==r) return;
    int mid=(l+r)>>1;
    build(l,mid,2*k);
    build(mid+1,r,2*k+1);
}

void updata(int l,int r,int k,int pos)
{
    if (l==r)
    {
        if (x[pos].size()) maxy[k]=*(--x[pos].end());
        else maxy[k]=-1;
        return;
    }
    int mid=(l+r)>>1;
    if (pos>mid) updata(mid+1,r,2*k+1,pos);
    else updata(l,mid,2*k,pos);
    maxy[k]=max(maxy[2*k],maxy[2*k+1]);
}

int work(int l,int r,int k,int L,int R,int VAL)
{
    if ((maxy[k]<=VAL)||(L>R)) return -1;          //L>R即pos是最后一个值,pos+1就大于m-1;
    if (l==r) return l;
    int mid=(l+r)>>1;
    if (R<=mid) return work(l,mid,2*k,L,R,VAL);
    else if(L>mid) return work(mid+1,r,2*k+1,L,R,VAL);
    else
    {
        int t=work(l,mid,2*k,L,mid,VAL);
        if (t!=-1) return t;
        else return work(mid+1,r,2*k+1,mid+1,R,VAL);
    }
}

int main()
{
    scanf("%d",&n);
    for (int i=0;i<n;i++)
    {
        scanf("%s%d%d",a[i].ch,&a[i].x,&a[i].y);
        lisan[i]=a[i].x;
    }
    sort(lisan,lisan+n);
    m=unique(lisan,lisan+n)-lisan;
    build(0,m-1,1);
    for (int i=0;i<m;i++) x[i].clear();
    for (int i=0;i<n;i++)
    {
        int pos=lower_bound(lisan,lisan+m,a[i].x)-lisan;
        if (a[i].ch[0]=='a')
        {
            x[pos].insert(a[i].y);
            updata(0,m-1,1,pos);
        }
        else
        {
            if (a[i].ch[0]=='r')
            {
                x[pos].erase(a[i].y);
                updata(0,m-1,1,pos);
            }
            else
                {
                    int ans=work(0,m-1,1,pos+1,m-1,a[i].y);
                    if (ans==-1) printf("-1\n");
                    else printf("%d %d\n",lisan[ans],(*x[ans].upper_bound(a[i].y)));
                }
        }
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值