牛客多校补题 第二场 H Happy Triangle

Happy Triangle

题目链接

题目大意

有三种操作:
插入一个值x
删除一个值x
给一个x 问是否在数组里是否有两个值,可以与x构成三角形。

题解

与x构成三角形可以分为几种情况
x是最大边的时候
数组里比x小的最大的两个的和比x大就可以
x不是最大边的时候
找一个值,存在另一个值与这个值的差小于x
这种情况,这个两个值肯定是相邻的因为这样可以保证差最小,
第一种情况可以用set维护,第二种情况,线段树维护最小值就可以。线段树里维护的是与前一个的差值。
代码:

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <cmath>
#include <set>
#include <cstring>
#include <string>
#include <bitset>
#include <stdlib.h>
#include <time.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;
typedef set<int>::iterator sit;
#define st first
#define sd second
#define mkp make_pair
#define pb push_back
void wenjian(){freopen("concatenation.in","r",stdin);freopen("concatenation.out","w",stdout);}
void tempwj(){freopen("hash.in","r",stdin);freopen("hash.out","w",stdout);}
ll gcd(ll a,ll b){return b == 0 ? a : gcd(b,a % b);}
ll qpow(ll a,ll b,ll mod){a %= mod;ll ans = 1;while(b){if(b & 1)ans = ans * a % mod;a = a * a % mod;b >>= 1;}return ans;}
struct cmp{bool operator()(const pii & a, const pii & b){return a.second > b.second;}};
int lb(int x){return  x & -x;}
const int INF = 0x3f3f3f3f;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const int maxn = 2e5 + 4;
const int M = 4e4+2;
pii pp[maxn];
vector<int> v;
map<int,int> mm;
map<int,int> pos;
set<int> ss;
struct Node
{
    int l,r;
    ll num;
}node[maxn << 2];

void build(int l,int r,int no)
{
    node[no].l = l;
    node[no].r = r;
    node[no].num = inf;
    if(l == r)
    {
        return;
    }
    int mid = l + r>> 1;
    build(l,mid,no<<1);
    build(mid + 1,r,no<<1|1);
}
void update(int pos,ll num,int no)
{
    if(node[no].l > pos || node[no].r < pos)
        return;
    if(node[no].l == node[no].r)
    {
        node[no].num = num;
        return;
    }
    update(pos,num,no<<1);
    update(pos,num,no<<1|1);
    node[no].num = min(node[no<<1].num,node[no<<1|1].num);
}
ll query(int l,int r,int no)
{
    if(node[no].l > r || node[no].r < l)
        return inf;
    if(node[no].l >= l &&node[no].r <= r)
    {
        return node[no].num;
    }
    return min(query(l,r,no<<1),query(l,r,no<<1|1));
}

int main()
{
    int n;
    scanf("%d",&n);
    for (int  i=1 ; i <= n ; i++ )
    {
        scanf("%d%d",&pp[i].st,&pp[i].sd);
        v.pb(pp[i].sd);
    }
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    int m = v.size();
    build(1,m,1);
    for (int i = 0; i < v.size(); i ++ )
    {
        pos[v[i]] = i + 1;
    }
    for (int i =1 ; i <= n; i ++ )
    {
        int f = pp[i].st;
        int x = pp[i].sd;
        if(f == 1)
        {
            if(mm[x] == 0)
            {
                ss.insert(x);
                sit it = ss.find(x);
                if(it != ss.begin())
                {
                    sit itl = it;
                    itl -- ;
                    int s = x - *itl;
                    update(pos[x],s,1);
//                    printf("%d %d 111111\n",pos[x],s);
                }
                sit itr = it;
                itr ++;
                if(itr != ss.end())
                {
                    int temp = *itr;
                    if(mm[temp] == 1)
                    {
                        update(pos[temp],temp - x,1);
//                        printf("%d %d 1111111111\n",pos[temp],temp - x);
                    }
                }
            }
            else
            {
                update(pos[x],0,1);
//                printf("%d %d 1111\n",pos[x],0);
            }

            mm[x] ++;
        }
        else if(f == 2)
        {
            if(mm[x] == 1)
            {
                sit it = ss.find(x);
                sit itr = it;
                itr ++;
                if(itr != ss.end() && mm[*itr] == 1)
                {
                    int temp = *itr;
                    if(it == ss.begin())
                    {
                        update(pos[temp],inf,1);
//                        printf("%d %d 11111111\n",pos[temp],-1);
                    }
                    else
                    {
                        sit itl = it;
                        itl --;
                        int t = *itl;
                        update(pos[temp],temp - t,1);

                    }
                }
                update(pos[x],inf,1);
                ss.erase(x);
            }
            else if(mm[x] == 2)
            {
                sit it = ss.find(x);
                if(it != ss.begin())
                {
                    sit itl = it;
                    itl --;
                    int temp = *itl;
                    update(pos[x],x - temp,1);
                }
                else
                {
                    update(pos[x],inf,1);
                }
            }
            mm[x] -- ;
        }
        else
        {
            sit it = ss.lower_bound(x);
            if(mm[x] >= 2)
            {
                printf("Yes\n");
                continue;
            }
            else if(mm[x] == 1 && it != ss.begin())
            {
                printf("Yes\n");
                continue;
            }
            if(it != ss.begin())
            {
                sit itl = it;
                itl -- ;
                int temp = *itl;
                if(mm[temp] >= 2 && temp * 2 > x)
                {
                    printf("Yes\n");
                    continue;
                }
                if(itl != ss.begin())
                {
                    sit itll = itl;
                    itll --;
                    if(*itl + *itll > x)
                    {
                        printf("Yes\n");
                        continue;
                    }
                }
            }
            ll tt = query(pos[x],m,1);
            if(tt < x)
            {
                printf("Yes\n");
            }
            else
                printf("No\n");

        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值