zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校训练营(第二场)Happy Triangle

    题目链接

    https://ac.nowcoder.com/acm/contest/5667/H

    题目大意

    有 Q 次操作和一个集合 ,  操作有以下类型

    ①、向集合插入一个数 X 

    ②、从集合中删除一个 X

    ③、给定一个 X ,问能否从集合中挑选两个数 Y ,  Z 使得 X , Y , Z 能构成三角形

    解题思路 

    判断三角形的条件为两边之和大于第三边 , 两边之差小于第三边

    对于操作③每次询问的 X , 只有两种情况 : 1、X 为最大边 ,  2、 X 不为最大边

    若 X 为最大边 , 我们只要找到 X 的两个前驱并判断它们的和与 X 的大小关系即可

    若 X 不为最大边 , 我们就要找到一个比 X 大的数 , 以及这个数的前驱 , 然后判断它们的差值和 X 的大小关系

    对于 X 为最大边的情况我们用 set 简单维护一下就好

    对于 X 不为最大边的情况我们考虑用线段树维护每个数和它前驱的差值

    然后每次判断一下区间 [ X + 1 , MAX ] 的最小值和 X 的关系即可

    因为数很大 , 所以要离散化一下 ( 或者线段树动态开点也行

    AC_Code

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int INF (0x3f3f3f3f3f3f3f3fll);
    const int N = 3e5 + 10;
    struct Seg_Tree{
        int l , r , sum;
    }tree[N << 2];
    void push_up(int rt)
    {
        tree[rt].sum = min(tree[rt << 1].sum , tree[rt << 1 | 1].sum);
    }
    void build(int l , int r , int rt)
    {
        tree[rt].l = l , tree[rt].r = r , tree[rt].sum = INF;
        if(l == r) return ;
        int mid = l + r >> 1;
        build(l , mid , rt << 1);
        build(mid + 1 , r , rt << 1 | 1);
        push_up(rt);
    }
    void update(int pos , int val , int rt)
    {
        int l = tree[rt].l , r = tree[rt].r;
        if(l == r)
        {
            tree[rt].sum = val ;
            return ;
        }
        int mid = l + r >> 1;
        if(pos <= mid) update(pos , val , rt << 1);
        else update(pos , val , rt << 1 | 1);
        push_up(rt);
    }
    int query(int L , int R , int rt)
    {
        int l = tree[rt].l , r = tree[rt].r;
        if(L <= l && r <= R) return tree[rt].sum;
        int mid = l + r >> 1;
        int ans = INF;
        if(L <= mid) ans = min(ans , query(L , R , rt << 1));
        if(R > mid) ans = min(ans , query(L , R , rt << 1 | 1));
        return ans ;
    }
    set<int>se;
    map<int , int>cnt;
    int n , m;
    int op[N] , a[N] , b[N];
    int get_id(int x)
    {
        return lower_bound(a + 1 , a + 1 + m , x) - a;
    }
    void solve1(int pos)
    {
        int x = a[pos];
        cnt[x] ++ , se.insert(x);
        if(cnt[x] == 1)
        {
            auto it = se.lower_bound(x);
            it -- ; 
            if(it != se.begin()) update(pos ,  x - *it , 1);
            it ++ , it ++ ;
            if(it != se.end()) 
            {
                int now = query(get_id(*it) , get_id(*it) , 1);
                update(get_id(*it) , min(now , *it - x) , 1);
            }
        }
        else update(pos , 0 , 1);
            
    }
    void solve2(int pos)
    {
        int x = a[pos];
        cnt[x] -- ;
        if(cnt[x] == 1)
        {
            auto it = se.lower_bound(x);
            it -- ;
            if(it != se.begin()) update(pos , x - *it , 1);
            else update(pos , INF , 1);
        }
        else if(!cnt[x])
        {
            update(pos , INF , 1);
            se.erase(x);
            auto it = se.lower_bound(x) , jt = it;
            if(it != se.end())
            {
                int y = *it ;
                if(cnt[y] == 1)
                {
                    it -- ; 
                    if(it != se.begin()) update(get_id(y) , y - *it , 1);
                    else update(get_id(y) , INF , 1);    
                } 
            }
        }
    }
    bool solve3(int pos)
    {
        int x = a[pos];
        auto it = se.upper_bound(x) , jt = it;
        it -- ;
        if(it != se.begin()) 
        {
            int y = *it;
            if(cnt[y] > 1) if(y + y > x) return true;
            it -- ;
            if(it != se.begin()) if(y + *it > x) return true;
        }
        it = jt;
        int id = get_id(*se.lower_bound(x));
        int mi = query(id , m , 1);
        if(mi < x) return true;
        return false;
    }
    signed main()
    {
        ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0);
        se.insert(-INF);
        cin >> n;
        for(int i = 1 ; i <= n ; i ++)
        {
            cin >> op[i] >> a[i];
            b[i] = a[i];
        }
        sort(a + 1 , a + 1 + n);
        m = unique(a + 1 , a + 1 + n) - a - 1;
        build(1 , m , 1);
        for(int i = 1 ; i <= n ; i ++) b[i] = get_id(b[i]);
        for(int i = 1 ; i <= n ; i ++)
        {
            if(op[i] == 1) solve1(b[i]);
            else if(op[i] == 2) solve2(b[i]);
            else 
            {
                if(solve3(b[i])) cout << "Yes
    ";
                else cout << "No
    ";
            }
        }
        return 0;
    }
  • 相关阅读:
    Beyond Compare 4 过期操作
    python2 批量转 python3
    【JavaScript】为什么javascript是单线程
    Java之花样玩枚举
    OpenSSL
    OpenSSL和OpenSSH以及私有CA的实现
    Python-线程同步
    Zookeeper基础
    pycharm中使用git以及多分支结构
    BZOJ 4771 主席树+倍增+set
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/13345496.html
Copyright © 2011-2022 走看看