2021杭电多校第六场
1005:median
就是说m个集合对吧,那么首先把每个集合的中位数放进去,按中位数排个序,那么如果我们考虑从前面往后面枚举,在第一个集合的时候,相当于你要求小于这个中位数的有几个作为 \(lp = a[1] - a[0] - 1\),大于中位数的有几个作为 \(rp = n - m - lp\),判断一下,显然如果 \(lp > rp\),是无解的。如果 \(lp + 1 < rp\),那么右边太多了,就要继续去后边找,那么当前这个集合对后面的影响就是说多了一些自由元,就是说你前面的这些 \(lp\),你得在后面取数和它抵消掉,而且是随便取都可以的,那么就可以认为是自由元, \(num += lp + 1\),就是左边最多可以拿 \(lp + 1\)个来抵消,那么当枚举到后一个集合的时候,重新考虑\(lp = a[i] - a[i - 1] - 1,~rp = n - (m - i) - a[i]\),然后要考虑自由元 \(num\) 的影响,那么就是\(lp > rp + num\) 无解,\(lp + 1 + num < rp\),继续后移, 否则就有解了。
const int maxn = 1e5 + 10;
int a[maxn];
void run() {
int n = rd(), m = rd();
for(int i = 1; i <= m; ++ i) a[i] = rd();
sort(a + 1, a + 1 + m); int num = 0;
for(int i = 1; i <= m; ++ i) {
int l = a[i] - a[i - 1] - 1, r = n - m + i - a[i];
if(l > r + num) {
puts("NO");
return ;
}
else if(l + 1 + num < r) {
num += l + 1;
}
else {
puts("YES");
return ;
}
}
puts("NO");
return ;
}
signed mian() {
int t = rd();
while(t--) run();
return 0;
}

浙公网安备 33010602011771号