2020牛客多校二H Happy Triangle (STL 线段树)

题意:一个集合可以对其做三种操作,加上一个x,减去一个已有x,给出一个x问时候存在a和b使得abx可以围成一个三角形

分析:看到集合操作马上想到用set,其中可以再用set的指针在map上记录下所以数值之间的差,但这时存在一个问题就是可能存在两个数,这两个数的差满足条件但两个数的和却太小不到x,因此我所用的方法就是提前把所有差都求出来后离散键线段树,线段树上存的是该差中的最大和,这样再动态对每个操作进行修改查询

代码:

#include <bits/stdc++.h>
#define x first
#define y second
#define mid (l+r>>1)
#define lo (o<<1)
#define ro (o<<1|1)
using namespace std;
typedef long long ll;
typedef vector<int>vi;
typedef pair<int,ll>pii;
struct tri{int x,y,z;};
const int inf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f;
const int N=2e5+10;
const ll mod=1e9+7;
const double PI=acos(0)*2;

int n,m,o[N],x[N];
vector<pii>add[N],sub[N];
set<int>tong[N<<2];
int arr[N<<2];
ll ma[N<<3];

void update(int p,int v,int o=1,int l=1,int r=m)
{
    if(l==r)
    {
        ma[o]=v;
        return;
    }
    if(p<=mid)update(p,v,lo,l,mid);
    else update(p,v,ro,mid+1,r);
    ma[o]=max(ma[lo],ma[ro]);
}
ll query(int p,int o=1,int l=1,int r=m)
{
    if(r<=p)
    {
        return ma[o];
    }
    ll ret=query(p,lo,l,mid);
    if(p>mid)ret=max(ret,query(p,ro,mid+1,r));
    return ret;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
//    freopen("in.txt","r",stdin);
    map<ll,int>mp,s;
    mp[0]=1,mp[inf<<1]=1;
    s[inf<<1]=1;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int op,a;cin>>op>>a;
        o[i]=op;x[i]=a;
        if(op==1)
        {
            if(mp.count(a))
            {
                s[0]++;
                add[i].push_back({0,a*2});
            }
            else
            {
                auto l=mp.lower_bound(a);
                auto r=l--;

                int len=r->x-l->x;
                s[len]--;
                if(s[len]==0)s.erase(len);
                sub[i].push_back({len,r->x+l->x});

                s[r->x-a]++;
                add[i].push_back({r->x-a,r->x+a});
                s[a-l->x]++;
                add[i].push_back({a-l->x,a+l->x});
            }
            mp[a]++;
        }
        else if(op==2)
        {
            mp[a]--;
            if(mp[a]==0)
            {
                mp.erase(a);
                auto l=mp.lower_bound(a);
                auto r=l--;

                s[r->x-l->x]++;
                add[i].push_back({r->x-l->x,r->x+l->x});

                int tmp=a-l->x;
                s[tmp]--;
                if(!s[tmp])s.erase(tmp);
                sub[i].push_back({tmp,a+l->x});

                tmp=r->x-a;
                s[tmp]--;
                if(!s[tmp])s.erase(tmp);
                sub[i].push_back({tmp,a+r->x});
            }
            else
            {
                s[0]--;
                if(!s[0])s.erase(0);
                sub[i].push_back({0,a*2});
            }
        }
    }

    for(int i=1;i<=n;i++)
    {
        for(auto j:add[i])arr[++m]=j.x;
    }
    sort(arr+1,arr+1+m);
    m=unique(arr+1,arr+1+m)-arr;
//    for(int i=1;i<=m;i++)cout<<arr[i]<<' ';cout<<endl;

    unordered_map<int,int>id;
    for(int i=1;i<=m;i++)id[arr[i]]=i;

    for(int i=1;i<=n;i++)
    {
        for(auto j:add[i])
        {
            tong[id[j.x]].insert(j.y);
            update(id[j.x],*(--tong[id[j.x]].end()));
        }
        for(auto j:sub[i])if(j.x!=inf*2)
        {
            tong[id[j.x]].erase(j.y);
            int tmp=0;
            if(tong[id[j.x]].size())tmp=*(--tong[id[j.x]].end());
            update(id[j.x],tmp);
        }

        if(o[i]==3)
        {
            int p=lower_bound(arr+1,arr+1+m,x[i])-arr;
//            cout<<p<<endl;
            if(p>1&&query(p-1)>x[i])
            {
//                cout<<p-1<<' '<<query(p-1)<<endl;
                cout<<"Yes"<<endl;
            }
            else cout<<"No"<<endl;
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43700916/article/details/108659870