2020牛客多校 2H.Happy Triangle(动态开点线段树)

题意:

q次操作,操作有三种:
(1,x)在可重集S中插入一个x
(2,x)从可重集S中删除一个x,保证删除合法
(3,x)问能否从可重集S中找到两个数a,b,满足a,b,x可以构成三角形

数据范围:q<=2e5,1<=x<=1e9

解法:

题解:
在这里插入图片描述

询问的时候只有三种情况:
1.(a,b,x),这种情况那么找两个x前面最大的,判断一下就行了
2.(a,x,b)
3,(x,a,b)

1的情况我用了线段树找前驱

2和3的情况,其实就是要找到一组(a,b),满足b>=x且b-a<x,
只考虑相邻的a和b,可以再开一棵线段树,存每个点与前驱的差值,再维护差值的最小值。
但是如果存在a>=b且a==b,这种情况也可以(上面维护前驱差值的时候不考虑相同的数)
这种情况需要再维护一下每个数是否出现超过两次。

因为数据范围比较大,操作比较少,所以用动态开点搞。

code:

#include<bits/stdc++.h>
using namespace std;
const int maxm=6e5+5;
const int n=1e9+100;
int lc[maxm*40],rc[maxm*40];
int cnt[maxm*40],flag[maxm*40],midif[maxm*40];
int mi[maxm*40],ma[maxm*40];
int tot,rt1,rt2;
void pushup_cnt(int k){
    cnt[k]=0;
    flag[k]=0;
    mi[k]=2e9;
    ma[k]=0;
    if(lc[k]){
        cnt[k]+=cnt[lc[k]];
        flag[k]|=flag[lc[k]];
        mi[k]=min(mi[k],mi[lc[k]]);
        ma[k]=max(ma[k],ma[lc[k]]);
    }
    if(rc[k]){
        cnt[k]+=cnt[rc[k]];
        flag[k]|=flag[rc[k]];
        mi[k]=min(mi[k],mi[rc[k]]);
        ma[k]=max(ma[k],ma[rc[k]]);
    }
}
void pushup_dif(int k){
    midif[k]=2e9;
    if(lc[k])midif[k]=min(midif[k],midif[lc[k]]);
    if(rc[k])midif[k]=min(midif[k],midif[rc[k]]);
}
void update_cnt(int x,int val,int l,int r,int& k){
    if(!k)k=++tot;
    if(l==r){
        cnt[k]+=val;
        flag[k]=(cnt[k]>=2);
        mi[k]=(cnt[k]?l:2e9);
        ma[k]=(cnt[k]?l:0);
        return ;
    }
    int mid=(l+r)/2;
    if(x<=mid)update_cnt(x,val,l,mid,lc[k]);
    else update_cnt(x,val,mid+1,r,rc[k]);
    pushup_cnt(k);
}
void update_dif(int x,int val,int l,int r,int& k){
    if(!k)k=++tot;
    if(l==r){
        midif[k]=val;
        return ;
    }
    int mid=(l+r)/2;
    if(x<=mid)update_dif(x,val,l,mid,lc[k]);
    else update_dif(x,val,mid+1,r,rc[k]);
    pushup_dif(k);
}
int askma(int st,int ed,int l,int r,int k){
    if(!k||!cnt[k])return 0;
    if(st<=l&&ed>=r)return ma[k];
    int mid=(l+r)/2;
    int ans=0;
    if(st<=mid)ans=max(ans,askma(st,ed,l,mid,lc[k]));
    if(ed>mid)ans=max(ans,askma(st,ed,mid+1,r,rc[k]));
    return ans;
}
int askmi(int st,int ed,int l,int r,int k){
    if(!k||!cnt[k])return 2e9;
    if(st<=l&&ed>=r)return mi[k];
    int mid=(l+r)/2;
    int ans=2e9;
    if(st<=mid)ans=min(ans,askmi(st,ed,l,mid,lc[k]));
    if(ed>mid)ans=min(ans,askmi(st,ed,mid+1,r,rc[k]));
    return ans;
}
int askflag(int st,int ed,int l,int r,int k){
    if(!k||!flag[k])return 0;
    if(st<=l&&ed>=r)return flag[k];
    int mid=(l+r)/2;
    int ans=0;
    if(st<=mid)ans|=askflag(st,ed,l,mid,lc[k]);
    if(ed>mid)ans|=askflag(st,ed,mid+1,r,rc[k]);
    return ans;
}
int askmidif(int st,int ed,int l,int r,int k){
    if(!k||midif[k]==2e9)return 2e9;
    if(st<=l&&ed>=r)return midif[k];
    int mid=(l+r)/2;
    int ans=2e9;
    if(st<=mid)ans=min(ans,askmidif(st,ed,l,mid,lc[k]));
    if(ed>mid)ans=min(ans,askmidif(st,ed,mid+1,r,rc[k]));
    return ans;
}
//
void add(int x){
    if(askma(x,x,0,n,rt1)==x){
        update_cnt(x,1,0,n,rt1);
        return ;
    }
    int ma1=askma(0,x-1,0,n,rt1);
    int mi1=askmi(x+1,n,0,n,rt1);
    update_cnt(x,1,0,n,rt1);
    update_dif(mi1,mi1-x,0,n,rt2);
    update_dif(x,x-ma1,0,n,rt2);
}
void del(int x){
    update_cnt(x,-1,0,n,rt1);
    if(askma(x,x,0,n,rt1)==x)return ;
    int ma1=askma(0,x-1,0,n,rt1);
    int mi1=askmi(x+1,n,0,n,rt1);
    update_dif(mi1,mi1-ma1,0,n,rt2);
    update_dif(x,2e9,0,n,rt2);
}
//
int check1(int x){
    int b=askma(0,x,0,n,rt1);
    if(!b)return 0;
    update_cnt(b,-1,0,n,rt1);
    int a=askma(0,x,0,n,rt1);
    update_cnt(b,1,0,n,rt1);
    if(!a)return 0;
    return a+b>x;
}
int check2(int x){
    int f=askflag(x,1e9,0,n,rt1);
    if(f)return 1;
    int dif=askmidif(x,1e9,0,n,rt2);
    return dif<x;
}
//
signed main(){
    //init
    update_cnt(0,1e9,0,n,rt1);
    update_cnt(n,1e9,0,n,rt1);
    //
    int q;scanf("%d",&q);
    while(q--){
        int op,x;scanf("%d%d",&op,&x);
        if(op==1){
            add(x);
        }else if(op==2){
            del(x);
        }else if(op==3){
            int ok=(check1(x)||check2(x));
            if(ok)puts("Yes");
            else puts("No");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/107363099