Rudolf and Imbalance

会 G 不会 F 是不是没救了

Rudolf sorts the complexities of the problems in ascending order and finds the largest value of .

What is the minimum value of imbalance that Rudolf can achieve by adding at most one problem, created according to the described rules?

最大值最小化,是经典二分答案问题。直接二分所要求的最大值即可。

我们可以初始排序好 。每次 check 时,枚举相邻两个元素间的差。记当前要 check 的值为 。若 ,说明我们需要插入一个元素。

我们只能插入一个问题,即只能将一个段变小。因此遇到过长段时打上一个 flag,下次遇到过长段且有 flag 可以直接返回 false

而判断某个段内是否可以通过插入一道题的方式让区间变小,这就是“求是否可以在两个序列中各取出一个数使其和在某范围”的经典问题。枚举 中元素,求出若把段分成两个合法段需要的 中元素最小/最大是多少,再按照这个范围在 中二分就好了。

设二分的值域为 。每次 check 需要遍历 一次,最多会遍历 一次。遍历 时还需要在 内二分查找,因此 check 函数的时间复杂度为 ,总时间复杂度为

#include<bits/extc++.h>
using namespace std;
namespace pbds=__gnu_pbds;
using ui=unsigned int;
using uli=unsigned long long int;
using li=long long int;
int main(void){
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    size_t T;
    cin>>T;
    while (T--){
        size_t n,m,k;cin>>n>>m>>k;
        vector<ui> a(n),d(m),f(k);
        for (ui& i:a) cin>>i;
        for (ui& i:d) cin>>i;
        for (ui& i:f) cin>>i;
        sort(a.begin(),a.end()),sort(d.begin(),d.end()),sort(f.begin(),f.end());
        ui l=0,r=2e9+1;
        auto check=[&](ui mid){
            bool flag=false;
            for (size_t i=1;i<n;++i) if (a[i]-a[i-1]>mid){
                if (flag) return false;
                flag=true;
                for (ui j:d){
                    vector<ui>::const_iterator it=a[i]-mid>=j?lower_bound(f.cbegin(),f.cend(),a[i]-mid-j):f.cbegin(),
                                               jt=a[i-1]+mid>=j?upper_bound(f.cbegin(),f.cend(),a[i-1]+mid-j):f.cbegin();
                    if (it<jt) goto getit;
                }
                return false;
                getit:;
            }
            return true;
        };
        while (l<r){
            ui mid=(l+r)/2;
            check(mid)?r=mid:l=mid+1;
        }
        cout<<l<<'\n';
    }
    return 0;
}
posted @ 2024-03-13 09:26  MrPython  阅读(6)  评论(0)    收藏  举报  来源