zoukankan      html  css  js  c++  java
  • CF 19D

    题目在这:

    给出三种操作:
    1.增加点(x,y)
    2.删除点(x,y)
    3.询问在点(x,y)右上方的点,如果有相同,输出最左边的,如果还有相同,输出最低的那个点

    分析:
    线段树套平衡树。
    我们先离散化输入的x坐标,然后以每个坐标建立一棵平衡树来维护,这里可以直接用set或者map来维护就行了。

    然后我们现在需要在x的右方找到最左最下大于(x,y)的点。
    建立一棵线段树,维护的是区间的纵坐标的最值,而线段树的端点为离散后x的值。

    1.我们每次插入的时候,直接在相应的平衡树中插入,然后更新一下线段树的区间最值。
    2.删除时,直接删掉,更新一下最值。
    3.询问时,对于整个区间,我们找到比x大的区间,利用区间最值,从左往右找是否存在大于y的点。最后输出即可。

    具体看代码。。。

    #include <set>
    #include <map>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    
    #define debug puts("here")
    #define rep(i,n) for(int i=0;i<n;i++)
    #define rep1(i,n) for(int i=1;i<=n;i++)
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
    #define pb push_back
    #define RD(n) scanf("%d",&n)
    #define RD2(x,y) scanf("%d%d",&x,&y)
    #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
    #define All(vec) vec.begin(),vec.end()
    #define MP make_pair
    #define PII pair<int,int>
    
    /******** program ********************/
    
    const int MAXN = 2e5+5;
    
    int id[MAXN];
    set<int> se[MAXN];
    
    struct Data{
        char op;
        int x,y;
    }d[MAXN];
    
    struct node{
        int l,r,mx;
        inline int mid(){
            return (l+r)>>1;
        }
    }tree[MAXN<<2];
    
    void build(int l,int r,int rt){ // 建树
        tree[rt].l = l;
        tree[rt].r = r;
        tree[rt].mx = -1;
        if(l==r){
            se[l].clear();	// 平衡树清空
            return;
        }
        int mid = tree[rt].mid();
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
    }
    
    void update(int x,int rt){ // 更新操作
        if(tree[rt].l==tree[rt].r){
            if(se[x].size()==0) // 如果为空
                tree[rt].mx = -1;
            else{
                set<int>::iterator it = se[x].end(); // 最大值其实就是最后一个元素
                tree[rt].mx = *--it;
            }
            return;
        }
        int mid = tree[rt].mid();
        if(x<=mid)   update(x,rt<<1);
        else        update(x,rt<<1|1);
        tree[rt].mx = max(tree[rt<<1].mx,tree[rt<<1|1].mx);
    }
    
    int ask(int x,int y,int rt){
        if(tree[rt].l==tree[rt].r)
            return tree[rt].l;
        if( tree[rt<<1].r>x && tree[rt<<1].mx>y ){ // 如果左儿子区间存在比x大且最值大于y,可能在左儿子区间
            int t = ask(x,y,rt<<1);
            if(t!=-1)   return t;
        }
        if( tree[rt<<1|1].mx>y ) // 这里右儿子的右端点显然比x大
            return ask(x,y,rt<<1|1);
        return -1;
    }
    
    int main(){
    
    #ifndef ONLINE_JUDGE
    	freopen("sum.in","r",stdin);
    	//freopen("sum.out","w",stdout);
    #endif
    
        int n;
        int ncase = 0;
        while(cin>>n){
            ncase?puts("----------------"):ncase = 1;
            char op[10];
            vector<int> vec;
            rep1(i,n){
                scanf("%s%d%d",op,&d[i].x,&d[i].y);
                d[i].op = op[0];
                vec.pb(d[i].x);
            }
            sort(All(vec));
            vec.erase( unique(All(vec)),vec.end() ); // 去重
            foreach(i,vec)
                id[i] = vec[i];
            int len = vec.size();
    
            build(0,len+10,1);
    
            rep1(i,n){
                int x = lower_bound(id,id+len,d[i].x)-id+1; // 二分出x离散后的值
    			
                int y = d[i].y;
                if(d[i].op=='a'){
                    se[x].insert(y);
                    update(x,1);
                }
                else if(d[i].op=='r'){
                    se[x].erase(y);
                    update(x,1);
                }
                else{
                    int t = ask(x,y,1);
                    if(t==-1)
                        puts("-1");
                    else
                        printf("%d %d
    ",id[t-1],*se[t].upper_bound(y)); // 二分出比y大的值
                }
            }
        }
    
    
    	return 0;
    }
    

      

  • 相关阅读:
    移动端web页面使用position:fixed问题
    登录的一些心得
    响应式网页设计
    xss(跨站脚本攻击),crsf(跨站请求伪造),xssf
    HTML5 离线功能介绍
    webapp开发经验和资料
    学习Java,值得你留意的问题(1)更名为《学习Java,容易被你忽略的小细节(1)》
    Python下搜索文件
    从百度地图API接口批量获取地点的经纬度
    获取代理IP地址(BeautifulSoup)
  • 原文地址:https://www.cnblogs.com/yejinru/p/3155834.html
Copyright © 2011-2022 走看看