CF1418D Trash Problem

题目传送门

思路

这题其实非常的简单,完全到不了 \(\mathcal *2100\)

发现这个题目描述有点诈骗,但是翻译的挺不错,实质上问题就是给你 \(n\) 个点,让你动态维护相邻两个点的差值,最后答案即为 \(\max-\min-\) 最大差值。

于是我们可以二分套动态开点权值线段树或者直接 \(\mathcal multiset\) 瞎搞。

为了简单,可以使用 \(\mathcal multiset\),但是注意插入和删除都需要分类讨论,思路非常简单,可能码量有一点点长。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
int const N=1e5+10;
int p[N];
multiset<int>s,S;
inline void cr(int x){
    if (!s.size()){s.insert(x);return;}
    if (s.lower_bound(x)==s.end()){
        int pl=*(--s.lower_bound(x));
        S.insert(x-pl);
    }else if (s.lower_bound(x)==s.begin()){
        int pl=*s.begin();
        S.insert(pl-x);
    }else{
        int pl1=*(--s.lower_bound(x));
        int pl2=*(s.lower_bound(x));
        S.erase(S.lower_bound(pl2-pl1));
        S.insert(x-pl1);S.insert(pl2-x);
    }
    s.insert(x);
}
inline void del(int x){
    s.erase(s.lower_bound(x));
    if (!s.size()) return;
    if (s.lower_bound(x)==s.end()){
        int pl=*(--s.lower_bound(x));
        S.erase(S.lower_bound(x-pl));
    }else if (s.lower_bound(x)==s.begin()){
        int pl=*s.begin();
        S.erase(S.lower_bound(pl-x));
    }else{
        int pl1=*(--s.lower_bound(x));
        int pl2=*(s.lower_bound(x));
        S.insert(pl2-pl1);
        S.erase(S.lower_bound(x-pl1));
        S.erase(S.lower_bound(pl2-x));
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int n,q;cin>>n>>q;
    for (int i=1;i<=n;++i) cin>>p[i],s.insert(p[i]);
    sort(p+1,p+n+1);
    for (int i=2;i<=n;++i) S.insert(p[i]-p[i-1]);
    if (s.size()<=1) cout<<"0\n";
    else cout<<(*(--s.end()))-(*s.begin())-(*(--S.end()))<<'\n';
    while (q--){
        int opt,x;cin>>opt>>x;
        if (opt==1) cr(x);
        else del(x);
        if (s.size()<=1) cout<<"0\n";
        else cout<<(*(--s.end()))-(*s.begin())-(*(--S.end()))<<'\n';
    }
    return 0;
}

应该非常好理解,插入和删除的分讨是一样的,还有输出答案需要判 \(\mathcal set\) 中是否还有值。

posted @ 2022-11-09 08:08  Tx_Lcy  阅读(24)  评论(0)    收藏  举报