CF1712D题解

0htoAi

2022-08-15 20:21:51

题解

这题有个显然的二分做法,可是我考场没想到,所以直接贪心的。虽然考场上没有 AC,但是做法跟补题的时候的做法也差不多。

考虑原图中任意两个点 (l,r)1 \leq l < r \leq n,它们之间的最短路只有可能是这两种情况之一:

其实可能出现 a_{\min}=\min_{i=l}^{r}(a_i) 的情况,不过由于最短路是以上两种情况取较小值,所以可以忽略这个问题。

首先明确只要改变一个点的值,一定把其改成最大值,即 10^9

然后分类讨论:

如果题解看糊涂了可以看代码:

#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e6+50;
int N,K;
struct Dot
{
    int Val,id;
}d[MAXN];
bool cmp(Dot a,Dot b)
{
    return a.Val<b.Val;
}
int a[MAXN];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&N,&K);
        for(int i=1;i<=N;i++)
        {
            scanf("%d",&d[i].Val);
            d[i].id=i;
            a[i]=d[i].Val;
        }
        if(K==N)
        {
            puts("1000000000");
            continue;
        }
        sort(d+1,d+N+1,cmp);
        int ans1,ans2,ans3,ans4;
        if(K==1)
        {
            ans1=d[1].Val*2;
            ans2=0;
            for(int i=1;i<=N;i++)
            {
                ans2=max(ans2,a[i]);
            }
            ans3=d[2].Val*2,ans4=0;
            a[d[1].id]=1000000000;
            for(int i=1;i<N;i++)
            {
                ans4=max(ans4,min(a[i],a[i+1]));
            }
            printf("%d\n",max(min(ans1,ans2),min(ans3,ans4)));
            continue;
        }
        ans1=min(1000000000,d[K+1].Val*2),ans2=0;
        for(int i=1;i<=K;i++)
        {
            a[d[i].id]=1000000000;
        }
        for(int i=1;i<N;i++)
        {
            ans2=max(ans2,min(a[i],a[i+1]));
        }
        ans1=min(ans1,ans2);
        printf("%d\n",max(min(1000000000,d[K].Val*2),min(ans1,ans2)));
    }
}