首页 > 其他分享 >[题解]CF1712D Empty Graph

[题解]CF1712D Empty Graph

时间:2024-06-24 12:35:52浏览次数:20  
标签:min int 题解 s1 CF1712D leq sim s2 Empty

思路

因为我们枚举的直径是具备单调性的,所以可以使用二分答案。

我们可以想一个事情,如果有两个点 \(u\) 和 \(v\),它们两点之间的最短路径要么是直接从 \(u \to v\);要么是经过一个中转点 \(t\),即:\(u \to t \to v\)。

然后,我们可以发现一个显然的规律,就是 \(t\) 一定是区间 \(a\) 中最小值的下标。

知道了这些,我们便可以得出一个结论:任意两点 \(u,v\) 的最短路径为 \(\min(\min_{l \leq i \leq r}a_i,2 \times \min_{1 \leq i \leq n}a_i)\)。

接着,我们的 \(\operatorname{check}\) 函数就很好想了。

我们根据上面的公式,可以推断出对于一个 \(i(l \leq i \leq r)\),如果 \(2 \times a_i < x\) 那么这个点是一定要修改的。

我们这些数是可以用前缀和维护的,于是我们可以用两个数组 \(s1,s2\) 分别维护 \(1 \sim i\) 和 \(i \sim n\) 区间中的修改的数量。

随后,我们枚举一下 \(1 \sim n - 1\),判断一下 \(a_i < x\) 和 \(a_{i + 1} < x\)。

最终我们的修改次数就是 \(\min(s1_{i - 1} + s2_{i + 2} + (a_i < x) + (a_{i + 1} < x))\)。

Code

#include <bits/stdc++.h>  
#define re register  
  
using namespace std;  
  
const int N = 1e5 + 10,inf = 1e9 + 10;  
int T,n,k;  
int arr[N],s1[N],s2[N];  
  
inline int read(){  
    int r = 0,w = 1;  
    char c = getchar();  
    while (c < '0' || c > '9'){  
        if (c == '-') w = -1;  
        c = getchar();  
    }  
    while (c >= '0' && c <= '9'){  
        r = (r << 3) + (r << 1) + (c ^ 48);  
        c = getchar();  
    }  
    return r * w;  
}  
  
inline bool check(int x){  
    int res = inf;  
    for (re int i = 1;i <= n;i++) s1[i] = s1[i - 1] + ((arr[i] << 1) < x);//前缀和   
    for (re int i = n;i;i--) s2[i] = s2[i + 1] + ((arr[i] << 1) < x);  
    for (re int i = 1;i < n;i++){//枚举 1 ~ n - 1   
        int cnt = s1[i - 1] + s2[i + 2];//记录当前答案   
        if (arr[i] < x) cnt++;  
        if (arr[i + 1] < x) cnt++;  
        res = min(res,cnt);//取 min   
    }  
    return (res <= k);//判断是否合法   
}  
  
int main(){  
    T = read();  
    while (T--){  
        int l = 0,r = 1e9;  
        n = read();  
        k = read();  
        s2[n + 1] = 0;//记得把这一位清零   
        for (re int i = 1;i <= n;i++) arr[i] = read();  
        while (l <= r){//二分板子   
            int mid = l + r >> 1;  
            if (check(mid)) l = mid + 1;  
            else r = mid - 1;  
        }  
        printf("%d\n",l - 1);//记得减 1   
    }  
    return 0;  
}  

标签:min,int,题解,s1,CF1712D,leq,sim,s2,Empty
From: https://www.cnblogs.com/WaterSun/p/18264798

相关文章

  • [题解]CF1704D Magical Array
    题意给定\(n\)个长度为\(m\)的数组,对于每一个数组选择下面任意一种操作进行若干次(操作二只能被一个数组选出)。\(c_{t,i}-1,c_{t,i-1}+1,c_{t,j}-1,c_{t,j-1}+1\)。\(c_{t,i}-1,c_{t,i-1}+1,c_{t,j}-1,c_{t,j-2}+1\)。最后输出选择操作二的数组......
  • [题解]CF1665E MinimizOR
    思路发现\(2^k\)大的数,最终的答案一定由前\(k+1\)小的元素组成。考虑数学归纳法,显然当\(k=1\)成立。假令\(k'\)时成立,证明\(k=k'+1\)时成立即可:若第\(k\)位有两个及以上的\(0\),显然最终答案的第\(k\)位一定为\(0\),因此考虑前面的\(k-1\)位,显然取......
  • [题解]CF1473D Program
    思路因为此题目中对于数的更新只能为\(1\),所以,如果我们找到了\([1,l-1]\)与\([r+1,n]\)中能获得的两个极值即可。我们为\(S\)赋予权值,用一个数组\(a\)储存:如果\(S_i\)为+,则其权值为\(1\)。否则其权值为\(-1\)。那么,在第\(i\)次操作后,能产生的数是\(\s......
  • [题解]CF1312E Array Shrinking
    思路本题为P3146变式,也算是一道很经典的区间DP题了。因为\(n\leq500\),考虑区间DP。定义\(dp_{i,j}\)表示操作\([i,j]\)区间剩余长度的最小值。那么,我们可以枚举一个中间值\(k\),可以显然地得到一个状态转移方程(即不能合二为一的情况):\[dp_{i,j}=\min(dp_{i,......
  • [题解]CF1223F Stack Exterminable Arrays
    CCF出的原题观摩一下。思路首先可以用一个Trie来维护。在这里对本文中的一些变量做一下说明。\(p\)表示当前维护的Trie中,指向的元素编号。\(t_i\)表示在Trie中编号为\(i\)的元素在原序列中的值。\(f_i\)表示在Trie中编号为\(i\)的元素在Trie中的父节点。......
  • [题解]CF1175E Minimal Segment Cover
    思路这是一道简单的DP题,DP题的核心就是状态转移。先来说一说\(dp\)数组的含义。\(dp_{i,j}\)表示从\(i\)这个点用\(2^j\)条线段能走到的最远的点。我们再来考虑一下边界情况。因为我们只用\(2^0\)条线段,那么:\(dp_{i,0}=\max(dp_{i,0},r)\)接着,我们递推一......
  • [题解]CF1092D1 Great Vova Wall (Version 1)
    思路发现,如果相邻元素的奇偶性相同,那么一定能通过在较低的位置竖着放若干个如果在\(i\)的位置竖着放一块砖头,使得这两列的高度相同。那么,我们想到直接考虑\(h_i\)的奇偶性,即将\(h_i\leftarrowh_i\bmod2\)。如果\(h_i=h_{i+1}\),我们显然可以同时使\(h_i\)和\(h......
  • [题解]CF1070C Cloud Computing
    思路考虑用线段树维护区间信息:价格在\([l,r]\)之间的CPU的数量。购买所有价格在\([l,r]\)之间CPU所需的钱。容易将区间修改转化为差分,从而实现单点修改。于是可以使用\(n\)个vector存储第\(i\)天所需进行的修改。查询第\(i\)天的答案时,如果不足\(k\)......
  • [题解]CF1746B Rebellion
    思路首先我们需要看到题目一个特殊的地方:这个序列中只存在\(0\)和\(1\)。那么,我们不难发现最终的答案一定是形如下面的序列:\(0,\dots,0,1,\dots,1\)。知道了这些,就很好想了。我们从后往前枚举,如果当前一位为\(0\)了,就从\(last\simi\)扫一遍,如果有\(1\)将最靠前的\(......
  • [题解]CF1742G Orray
    思路做这道题之前,首先要知道一个性质:\(a\operatorname{or}b\geqa\)。那么,我们就能得出一个结论:经过一定顺序的排列,最多经过\(\lceil\log_2^{a_{\max}}\rceil\)个数就能让前缀或的值达到最大值。我们不妨令有一个位置\(i\),\(b_1,b_2,\dots,b_{i-1}\)单调递增,而\(b_i......