HDU 7029 Median

HDU 7029 Median

题意:给定一个1 ~ n的序列,之后给出m个互不相同的数且都在1~m范围之内,之后要求将这n个数字划分为m个区间,每一个区间的中位数都是给定的数字,问是否存在合法的划分方案。

解题思路:将这m个数字在1~n的序列中标记,那么可以得到他们两两之间的差构成的区间(此处需要注意不要遗忘开头与尾部分),考虑其中最大的区间,可以发现当这个区间比其他的区间相加要小的情况下,此处可以做为一个缓存,去删除前方与后方的数,不管怎样的情况下都是有解的,而当这个最大的区间要比其他区间相加要大时,可以想到我们不断联合前方区间与后方区间来删除这个区间的数字仍然是不够的的,此时需要利用中位数向下取整的性质,每一个在这个区间之前的标记点都可以额外删除一个点,综上所述,此题得解。

解题代码:

#include <bits/stdc++.h>
using namespace std;
int t, n , m, b[200000];
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
    cin >> t;
    while(t--){
        cin >> n >> m;
        int mx = 0,cnt = 0,tot = 0;
        for(int i = 1;i <= m;i++)cin >> b[i];
		b[++m] = n + 1;
        sort(b + 1,b + m + 1);
		//通过b数组计算出最大差距,这是本题解决的关键所在
        for(int i = 1;i <= m;i++){
			tot += b[i] - b[i - 1] - 1;//tot记录出去已经给定数字以外的全部数字
            if(b[i] - b[i - 1] - 1 > mx){
                mx = b[i] - b[i - 1] - 1;
				//可以知道m个数每一个数都是出现在一个特定的集合中的,因此中位数小于自身的数就是当前位置减去1
                cnt = i - 1;
            }
        }
		//考虑最大的集合,前半部分的可以消去未被选择的数+前面的中位数个,而后面可以消去后方未被消去的数的个数
		//明显,如果这个数比最大部分来的多就是一种合法方案
        if(mx <= tot - mx + cnt)cout << "YES\n";
		else cout << "NO\n";
    }
    return 0;
}
posted @ 2021-08-09 10:37  0xYuk1  阅读(71)  评论(0)    收藏  举报