HHappy Triangle(询问是否构成三角形)

Posted starve_to_death

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HHappy Triangle(询问是否构成三角形)相关的知识,希望对你有一定的参考价值。

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

题意:给定空的容器multiset:MS,有q个操作,操作一为向MS中加入x,操作二为在MS删除x,操作三为询问在MS是否存在a,b与x能形成一个不退化的三角形。

分析:对于询问操作,有俩种情况,情况一是x作为最大边,这种情况只要判断在MS中小于等于x的最大的俩个数来判断能否形成三角形,用一个set容器即可搞定;

   情况二为x不作为最大边,假设有a<=b满足条件,因为这种情况b肯定比x大,而a在越接近于b的情况下,x,a,b更容易满足条件,转化为b-a越小越能满足条件,所以这中情况,只要找x后缀中与前驱a之差最小的值ans,若ans<x说明存在,否则不存在,这部分可以用线段树解决。

   而操作一和操作二根据线段树值的确立来进行相应的操作即可。

   (记得开ll)

技术图片
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define MP make_pair
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
typedef long long ll;
const int mod=1e9+7;
const int M=2e5+5;
const ll inf=1e18;
ll tr[M<<2],lisan[M],cnt[M],a[M],op[M],m;
multiset<ll>MS;
void pn(){
    puts("No");
}
void py(){
    puts("Yes");
}
void up(int root){
    tr[root]=min(tr[root<<1],tr[root<<1|1]);
}
void build(int root,int l,int r){
    tr[root]=inf;
    ///cout<<l<<" "<<r<<endl;
    if(l==r)
        return ;
    int midd=(l+r)>>1;
    build(lson);
    build(rson);
}
void update(int pos,ll c,int root,int l,int r){
    if(l==r){
        tr[root]=c;
        return ;
    }
    int midd=(l+r)>>1;
    if(pos<=midd)
        update(pos,c,lson);
    else
        update(pos,c,rson);
    up(root);
}
ll query(int L,int R,int root,int l,int r){
    if(L<=l&&r<=R)
        return tr[root];
    int midd=(l+r)>>1;
    ll minn=inf;
    if(L<=midd)
        minn=min(minn,query(L,R,lson));
    if(R>midd)
        minn=min(minn,query(L,R,rson));
    return minn;
}

void solve1(int x){
    int pos=lower_bound(lisan+1,lisan+1+m,x)-lisan;
    if(cnt[pos]){
        update(pos,0,1,1,m);
    }
    else{
        auto it=MS.lower_bound(x);
        auto tmp=it;
        ///更新当前插入位
        it--;
        update(pos,x-*it,1,1,m);
        ///更新当前插入位的后一位
        int pos2=lower_bound(lisan+1,lisan+1+m,*tmp)-lisan;
        if(cnt[pos2]<2)
            update(pos2,*tmp-x,1,1,m);
    }
    cnt[pos]++;
    MS.insert(x);
}
void solve2(int x){
    int pos=lower_bound(lisan+1,lisan+1+m,x)-lisan;
    if(cnt[pos]==2){
        auto it=MS.lower_bound(x);
        it--;
        update(pos,x-*it,1,1,m);
    }
    else if(cnt[pos]==1){
        update(pos,inf,1,1,m);
        auto pre=MS.lower_bound(x);pre--;
        auto las=MS.upper_bound(x);
        int pos2=lower_bound(lisan+1,lisan+1+m,*las)-lisan;
        if(cnt[pos2]<2){
            update(pos2,*las-*pre,1,1,m);
        }
    }
    cnt[pos]--;
    ///因为只删一个,所以不能直接删除
    auto it=MS.lower_bound(x);
    MS.erase(it);
}
void solve3(int x){
    ///x作为最大边
    auto it=MS.upper_bound(x);it--;
    if(it!=MS.begin()){
        auto tmp=it;it--;
        if(*tmp+*it>x){
            py();
            return ;
        }
    }
    ///x不作为最大边
    it=MS.upper_bound(x);
    int pos=lower_bound(lisan+1,lisan+1+m,*it)-lisan;
    if(query(pos,m,1,1,m)<x)
        py();
    else
        pn();
    return ;
}
int main(){
    int n,tot=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&op[i],&a[i]);
        lisan[++tot]=a[i];
    }
    lisan[++tot]=inf,lisan[++tot]=-inf;

    sort(lisan+1,lisan+1+tot);
    m=unique(lisan+1,lisan+1+tot)-lisan-1;
    MS.insert(inf),MS.insert(-inf);
    build(1,1,m);

    for(int i=1;i<=n;i++){
        if(op[i]==1)solve1(a[i]);
        else if(op[i]==2)solve2(a[i]);
        else solve3(a[i]);
    }
    return 0;
}
View Code

 

以上是关于HHappy Triangle(询问是否构成三角形)的主要内容,如果未能解决你的问题,请参考以下文章

[XSY 1158] Triangle

hdu6601 Keen On Everything But Triangle 主席树+斐波那契数列妙用

BZOJ1914: [Usaco2010 OPen]Triangle Counting 数三角形

判断输入三个正整数是否构成直角三角形(是:Yes;不是:No;不构成三角形:Not a trangle)

POJ2079 Triangle

打印三角形