【Newcoder】2020牛客暑期多校训练营(第二场)H - Happy Triangle | STL、离散化、线段树

题目链接:https://ac.nowcoder.com/acm/contest/5667/H

害,由于网上的思路没有相同的..

自己写就debug了一天..

题目大意:

给你一个Multiset,支持三种操作:

1.集合中加入一个数x

2.集合中删除一个数x

3.询问集合中是否能选择两条边与x构成三角形

题目思路:

考虑题目里面有Multiset,那么就用一下Multiset。

对于一个满足要求的三角形来说,我们得知要满足 :a+b>c 或者 a-b<c

首先考虑对于询问的一个x来说

考虑三种情况:

(1) 作为最大边,此时需要求一下小于它的最大的两条边

(2) 作为中间边,此时需要求下小于它的,大于它的最小的

(3) 作为最小边,此时需要求一下大于它的两边的最小差值 | a-b<c

所以考虑第一种情况与第二种情况统统用Multiset实现

第三种情况维护最小差值,如果在线处理的话可能需要平衡树?(暂时鸽这,待补)

但是既然是询问,不妨离线处理一下

因为离线处理,那么就知道了所有询问点(有用点)

依次建线段树维护最小差值,查询大于x的最小差值也就是查询[getid(x),nn]的最小差值

依次将询问的x的通过以上三种情况考虑

便可以得出结论

第二种第三种情况(有注释)及线段树维护最小差值详见代码

Code:

/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC option("arch=native","tune=native","no-zero-upper")
#pragma GCC target("avx2")
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pp;
const ll INF=1e17;
const int Maxn=2e7+10;
const int maxn =2e5+10;
const int mod=998244353;
const int Mod = 1e9+7;
const double eps=1e-3;
inline bool read(ll &num)
{char in;bool IsN=false;
    in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
struct Query{
    int op,x;
}q[maxn];
vector<int>v;
struct node{
    ll maxl,minl;
    ll mi,val;
    node(){maxl = -INF;minl = mi = INF;val = 0;}
}t[maxn*4];
multiset<ll>s;
void push(int k){
    t[k].maxl = max(t[k<<1].maxl,t[k<<1|1].maxl);
    t[k].minl = min(t[k<<1].minl,t[k<<1|1].minl);
    t[k].mi = min(t[k<<1].mi,t[k<<1|1].mi);
    t[k].mi = min(t[k].mi,t[k<<1|1].minl-t[k<<1].maxl);
}
void Insert(int k,int l,int r,int pos,int w){
    if(l == r){
        t[k].val += w;
        t[k].maxl = -INF;
        t[k].mi = t[k].minl = INF;
        if(t[k].val){
            t[k].maxl = t[k].minl = v[l-1];
            if(t[k].val >= 2) t[k].mi = 0;
        }
        return;
    }
    int mid = (l+r)/2;
    if(pos<=mid) Insert(k<<1,l,mid,pos,w);
    else Insert(k<<1|1,mid+1,r,pos,w);
    push(k);
}
void query_mi(int k,int l,int r,int x,int y,ll &ans,ll &pre){
    if(x<=l&&y>=r){
        ans = min(ans,t[k].mi);
        ans = min(ans,t[k].minl-pre);
        pre = t[k].maxl;
        return ;
    }
    int mid = (l+r)/2;
    if(x<=mid) query_mi(k<<1,l,mid,x,y,ans,pre);
    if(y>mid) query_mi(k<<1|1,mid+1,r,x,y,ans,pre);
}
int query_val(int k,int l,int r,int pos){
    if(l == r) return t[k].val;
    int mid = (l+r)/2;
    if(pos<=mid) return query_val(k<<1,l,mid,pos);
    return query_val(k<<1|1,mid+1,r,pos);
}
int nn;
int getid(ll x){
    return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
int check(int i){
    int x,y;
    int id = getid(q[i].x);
    int cot = query_val(1,1,nn,id);
    auto temp = s.lower_bound(q[i].x);
    if(cot>=2) return 1;///等边三角形
    ///作为最大边
    if(temp != s.begin()){
        if(cot == 1) return 1;
        else{
            x = *prev(temp);
            if(prev(temp)!=s.begin()){
                y = *prev(prev(temp));
                if(x+y>q[i].x) return 1;
            }
        }
    }

    ///作为中间边
    if(cot == 1){
        if(temp != s.begin()) return 1;
        auto tempx = s.upper_bound(q[i].x);
        if(tempx != s.end() && (*tempx)<2ll*q[i].x) return 1;
    }
    else if(temp != s.end()&& temp != s.begin()){
        x = *prev(temp),y = *temp;
        if(x+q[i].x>y) return 1;
    }
    ///作为最小边
    ll pre = -INF,ans = INF;
    query_mi(1,1,nn,id,nn,ans,pre);
    if(ans<q[i].x) return 1;
    return 0;
}
int main(){
   /* s.insert(3);s.insert(3);s.insert(2);s.erase(3,1);
    for(int x:s){
        debug(x);
    }*/
    read(n);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&q[i].op,&q[i].x);
        v.push_back(q[i].x);
    }
    sort(v.begin(),v.end());
    v.erase((unique(v.begin(),v.end())),v.end());
    nn = v.size();
    ///debug(nn);
    for(int i=1;i<=n;i++){
        int f = 0;
        int id = getid(q[i].x);
        if(q[i].op == 1) Insert(1,1,nn,id,1),s.insert(q[i].x);
        else if(q[i].op == 2){
            Insert(1,1,nn,id,-1);
            auto temp = s.lower_bound(q[i].x);
            if(*temp == q[i].x) s.erase(temp);
        }
        else if(q[i].op == 3){
            if(check(i))  printf("Yes\n");
            else printf("No\n");
        }
    }
    return 0;
}
/**

**/

猜你喜欢

转载自blog.csdn.net/qq_43857314/article/details/107374384