2020牛客多校第二场 H题Happy Triangle(动态开点线段树)

2020牛客多校第二场 H题Happy Triangle(动态开点线段树)

Happy Triangle

题意:q次询问,3种操作,1:加入一个x,2:删除一个x,3,问能否在加入的边中找两条与x组成3角形。

题解:设三角形3边a,b,x;

其1:a+b>x;

其2:abs(a-b)<x;

由于其二的特性,我们要尽量找靠的近的a与b既可,例如,a与b间有一个数c,如果a,b满足公式,那c+b>x,

b-c<x,所以选c不会影响答案,即可以贪心的找靠在一起的边,那么要满足一条我们至少要使b>=x/2+1,这样a+b才能满足第一个条件(第一的b要特判),然后我们就找大于b的最小的间隔距离(用动态开点线段树既可)。

#include<iostream>
#include<cstring>
#include<map>
using namespace std;
#define ll long long
const ll maxn=1e9+7,inv=2e9+7;
ll q,op,x,k,cnt;
ll ans[3000007],lc[3000007],rc[3000007];
map<ll,ll>ma;

void up(ll &k,ll l,ll r,ll pos,ll z){
    if(!k){
        k=++cnt;
    }
    if(l==r){
        ans[k]=z;
        return;
    }
    ll mid=(l+r)/2;
    if(pos<=mid)up(lc[k],l,mid,pos,z);
    else{
        up(rc[k],mid+1,r,pos,z);
    }
    ans[k]=min(ans[lc[k]],ans[rc[k]]);
}
void add(ll x){
    ma[x]++;
    auto it=ma.lower_bound(x),it2=it;
    it++;
    it2--;
    if(it->first!=inv){
        if(it->second<=1){
            up(k,1,maxn,it->first,it->first-x);
        }
        else{
            up(k,1,maxn,it->first,0);
        }
    }
    if(ma[x]<=1){
        up(k,1,maxn,x,x-it2->first);
    }
    else{
        up(k,1,maxn,x,0);
    }
}
void del(ll x){
    auto it=ma.lower_bound(x),it2=it;
    it++;
    it2--;
    ma[x]--;
    if(ma[x]==0){
        ma.erase(x);
        up(k,1,maxn,x,inv);
        if(it->first!=inv&&it->second==1){
            up(k,1,maxn,it->first,it->first-it2->first);
        }
    }
    else if(ma[x]==1){
        up(k,1,maxn,x,x-it2->first);
    }
}
ll findz(ll k,ll l,ll r,ll ql,ll qr){
    if(ql<=l&&r<=qr){
        return ans[k];
    }
    ll mid=(l+r)/2,ans1=inv,ans2=inv;
    if(ql<=mid){
        ans1=findz(lc[k],l,mid,ql,qr);
    }
    if(qr>mid){
        ans2=findz(rc[k],mid+1,r,ql,qr);
    }
    return min(ans1,ans2);
}

ll query(ll x){
    ll qans=inv;
    auto it=ma.lower_bound(x/2+1),it2=it;
    it2--;
    if(it->first==inv){
        return inv;
    }
    if(it->second>=2){
        qans=0;
    }
    if(it->first+it2->first>x){
        qans=min(it->first-it2->first,qans);
    }
    it++;
    if(it->first==inv){
        return qans;
    }
    else{
        qans=min(qans,findz(k,1,maxn,it->first,maxn));
    }
    return qans;
}
int main(){
    memset(ans,inv,sizeof(ans));
    scanf("%lld",&q);
    ma[-inv]++;
    ma[inv]++;
    while(q--){
        scanf("%lld%lld",&op,&x);
        if(op==1){
            add(x);
        }
        if(op==2){
            del(x);
        }
        if(op==3){
            if(query(x)<x){
                printf("Yes\n");
            }
            else{
                printf("No\n");
            }
        }
    }
}

posted @ 2020-07-17 22:13  ccsu_madoka  阅读(229)  评论(0编辑  收藏  举报