codeforces 19D

题意:

n个操作,在200000*200000的平面上加删点

find 严格在坐标右上角,x最小,再y最小的点

思路:线段树套set,注意这种线段树二分的复杂度也是log。

#include <bits/stdc++.h>
#define ls x<<1
#define rs x<<1|1
#define lc l,mid,x<<1
#define rc mid+1,r,x<<1|1
using namespace std;
const int maxn = 200005;
const int inf = 0x3f3f3f3f;
multiset<int> se[maxn];
int tree[4*maxn];
vector<int> ve;
void discrete(){
    sort( ve.begin(),ve.end() );
    ve.erase( unique( ve.begin(),ve.end() ),ve.end() );
}
int H( int x ){
    return lower_bound( ve.begin(),ve.end(),x ) -ve.begin()+1;
}
void push_up( int x ){
    tree[x] = max(tree[ls] , tree[rs]);
}
void build( int l,int r,int x ){
    if( l == r ){
        tree[x] = -inf;
        return;
    }
    int mid = l+r>>1;
    build(lc);
    build(rc);
    push_up(x);
}
void update( int left,int right,int v,int l,int r,int x ){
    if( left <= l && right >= r ) {
        tree[x] = v;
        return;
    }
    int mid = l+r >>1;
    if(left <= mid)update( left,right,v,lc );
    else update( left,right,v,rc );
    push_up(x);
}
int query( int left,int right,int v,int l,int r,int x ){
    if( l == r ){
        if( tree[x] > v ) return l;
        else return -1;
    }
    if( tree[x] <= v ) return -1;
    int mid = l+r>>1;
    int res=-1;
    if( left <= mid ){
        res = query( left,right,v,lc );
    }
    if( res == -1 && right > mid ){
        res = query( left,right,v,rc );
    }
    return res;
}
struct Q{
    char c;
    int x,y;
    Q( char _c,int _x,int _y ){
        c = _c;x = _x;y = _y;
    }
};
vector<Q> v;
int main(){
    char ss[10];
    int n,x,y;scanf("%d",&n);
    for( int i = 1;i <= n;i++ ){
        scanf("%s%d%d",ss,&x,&y);
        ve.push_back(x);
        v.push_back( Q( ss[0],x,y ) );
    }
    discrete();
    build( 1,ve.size(),1 );
    for( int i = 0;i < v.size();i++ ){
        int x = H( v[i].x ),y = v[i].y;char c = v[i].c;
        if( c=='a'){
            se[x].insert( y );
            auto p = se[x].end();--p;
            update( x,x,*p,1,n,1 );
        }else if( c == 'r' ){
            se[x].erase(y);
            auto p = se[x].end();
            if( se[x].size() ) {
                --p;
                update(x, x, *p, 1, n, 1);
            }else  update(x, x,-inf , 1, n, 1);
        }else if( c=='f' ){
            if(x < ve.size() )
            x = query( x+1,ve.size(),y,1,n,1 );
            else x = -1;
            if( x == -1 ){
                puts("-1");
                continue;
            }
            auto p = se [x].upper_bound( y );
            if( p == se[x].end() ){
                puts("-1");
                continue;
            }
            printf("%d %d\n",ve[x-1],*p);
        }
    }
    return 0;
}
/*
 * 13
find 0 0
add 0 0
find 0 0
add 1 2
add 1 3
add 1 10
add 10 5
add 2 1
find 0 1
find 0 2
remove 1 10
remove 1 3
find 0 2
 */

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值