CF 798D Mike and distribution

CF 798D Mike and distribution

题目链接:洛谷 CF 798D Mike and distribution CF 798D Mike and distribution

算法标签: 贪心思维

题目描述:

给两个长度为 (n) 的数列(A,B),要求至多选择 $lfloor frac{n}{2} floor+1 $ 个下标,使得 (A) 数组中选出的数的和的两倍大于 (sumA)(B) 数组中选出的数的和的两倍大于 (sumB)

题解:

贪心 + 思维!!!!

模拟赛T1,三个小时没有搞出正解 [擦汗.jpg]

既然题目中让我们最多选择 (lfloor frac{n}{2} floor+1) ,并且没有要求最小,那么不妨我们就取 (lfloor frac{n}{2} floor+1) 个值,显然这是对的(不要白不要啊……)。

之后我们考虑假如只有一个数列,这道题就变得很简单,排序之后找出前 (lfloor frac{n}{2} floor+1) 个再判一下就可以。

那么对于两个数列怎么办???

现在我们来考虑这个神奇的 (lfloor frac{n}{2} floor+1) ,本着给你就不白给的原则,我们会发现,这是什么

​ —— 两两分组再加一个

虽然很奇妙且扯皮淡雅,但是这的确是真的啊(考场上怎么可能 (yy) 出来???)

又因为排序可以处理两个数列中的一个,那么两两分组就可以处理第二个。 [肯定.jpg]


用结构体 (node[~].a, node[~].b, node[~].id) 存下来 (A,B) 数组和当前这对数在初始数列的位置。

首先按照数列(A)从大到小给结构体排序,我们就得到了一个 (node[1].a ge node[2].a ge node[3].a dots ge node[n].a) 的有序结构体,这样我们保证前 (lfloor frac{n}{2} floor+1)(A)之和一定比剩下的(A)之和大。

之后我们假设先选择 (node[1]),之后对于后边的每一对值(两个值),选择其中 (B) 更大的一个,即对于(node[2].b)(node[3].b),选出更大的一个;对于 (node[4].b,node[5].b) ,选出更大的一个……

这时反观 (A) 的正确性,由于我们会发现 (node[1].a ge max(node[2].a, node[3].a),min(node[2].a, node[3].a) ge max(node[4].a, node[5].a) dots)

所以现在 (A) 的正确性也是可以保证的。

之后就可以愉快的码代码了 !!! [开心.jpg]

AC代码

#include <bits/stdc++.h>

using namespace std;

#define setI(x) freopen(x".in", "r", stdin); 
#define setO(x) freopen(x".out", "w", stdout); 
#define setIO(x) setI(x) setO(x)

char *p1, *p2, buf[100000];

typedef long long ll;

#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )

ll rd() {
	ll x = 0, f = 1;
	char c = nc();
	while (c < 48) { 
		if (c == '-') { 
			f = -1;
		}
		c = nc();
	}
	while (c > 47) {
		x = (((x << 2) + x) << 1) + (c ^ 48);
		c = nc();
	}
	return x * f;
}

const int N = 100010;

typedef long long ll;

struct Node {
	ll a, b;
	int id;
} node[N];

bool cmp(Node A, Node B) {
	if (A.a == B.a) {
		return A.b > B.b;
	}
	return A.a > B.a;
}

int n;

int main() {
	// setIO("game")
	n = rd();
	for (int i = 1; i <= n; i ++ ) {
		node[i].a = rd();
		node[i].id = i;
	}
	for (int i = 1; i <= n; i ++ ) {
		node[i].b = rd();
	}
	sort(node + 1, node + 1 + n, cmp);
	printf("%d
", (n / 2) + 1);
	printf("%d ", node[1].id);
	for (int i = 2; i <= n; i += 2) {
		ll nowb = node[i].b;
		ll nxtb = node[i + 1].b;
		if (nowb > nxtb) {
			printf("%d ", node[i].id);
		}
		else {
			printf("%d ", node[i + 1].id);
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/littleseven777/p/11845617.html