(思维)Maximum Median CodeForces - 1201C

先附上题目链接
这题具体用到的方法我也说不上来,二分?贪心?前缀和?不过是挺多细节的一题.还是得把思路捋顺了再做会顺手一点.第一次做就贡献了好多发WA,第二次了还是贡献了几发…
具体思路就是先找到中点位置然后再进行一系列操作.用文字说可能有点麻烦.举一下列子
比如长度为7 数组为 1 2 3 4 6 8 10 中间值为4.可以先尝试操作一下.怎么加1能得到最优的答案(贪心过程).其实就是始终让中间的值+1.但是不能去模拟这个过程,因为复杂度很大.
换一下思路.其实就是让中间的值达到后面的值需要多少次操作.比如到达6需要两次.这时数组变成了 6 6 8 10(由于前面的数字是没有用的,所以可以忽略掉)而到达8需要的操作数(8-6)*2(这里的2是8的位置减去中点位置得到的,比如后面10的时候就是(10-8)*3).
所以要用一个d数组储存需要的操作数.然后用一个lower_bound得到第一个大于等于操作数的下标pos.如果等于操作数直接输出s[pos-1]就可以了.如果不等于,那么注意lower_bound返回的是第一个大于等于的.所以多余的操作数是k-d[pos-1].还有一个细节.就是可能k大于pos[n].那么要进行处理.这方面的问题我代码写的比较繁琐.就只提供一个思想.不具体说方法啦.
只要把思路捋顺,就不是大问题.对了,注意用long long 不然是会爆掉的.
附上繁琐的code

#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <stack>
#include <string.h>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
const int mn = 2e5+10;
typedef long long ll;
ll s[mn];
ll d[mn];
int main() {
	ll n,k;
	cin >> n >> k;
	for (ll i = 1; i <= n; ++i) cin >> s[i];
	sort(s + 1, s + 1 + n);
	ll pos = (n + 1) / 2;
	ll cnt = 1;
	for (ll i = pos + 1; i <= n; ++i) {
		d[i] = d[i-1]+(s[i] - s[i - 1])*cnt;
		++cnt;
	}
	ll tpos;
	if(k > d[n]) tpos = n+1;
	else{
		tpos = lower_bound(d+pos+1,d+n+1,k)-d;
	}
	if (d[tpos] == k) {
		cout << s[tpos];
		return 0;
	}
	ll len = tpos-pos;
	ll ans=s[tpos-1]+(k-d[tpos-1])/len;
	cout << ans;

	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45590210/article/details/104230194