CF1574D 贪心 hash

考虑处理出最大的m+1种方案,这些方案中一定有答案。

以m个冲突的方案为基础进行修改,若全取最大为不合法方案,则由某一个方案修改一个装备可以取到最优答案(会传递下去)

对于某个方案,我们可以尝试遍历它的所有位置,尝试把某个位置上的装备改为仅次于当前装备的装备。\(O(mn)\)​

写+调得很慢,按这个速度考场上铁定写不出

// Problem: D. The Strongest Build
// Contest: Codeforces - Educational Codeforces Round 114 (Rated for Div. 2)
// URL: https://codeforces.com/problemset/problem/1574/D
// Memory Limit: 256 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 7;
#define ll long long
#define ull unsigned long long
int rd() {
	int s = 0, f = 1; char c = getchar();
	while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
	while (c >= '0' && c <= '9') {s = s * 10 + c - '0'; c = getchar();}
	return s * f;
}
int n, m, k, tot, c[maxn];
set<ll, greater<ll> > slots[11];
typedef pair<ull, ull> pii;
set<pii, less<pii> > delta;
set<ull> crash;
ull a[11][maxn], ans[11];
ull b[maxn][11], C[maxn][11];
ull ha(ull *s) {
	ull res = 0;
	for (int i = 1; i <= n; i++) res = res * 19260817ull + s[i];
	return res;
}
bool check(ull *s) {
	return (crash.count(ha(s)));
}
ull rres = 0;
int main() {
	n = rd();
	for (int i = 1; i <= n; i++) {
		c[i] = rd();
		for (int j = 1; j <= c[i]; j++) {
			a[i][j] = rd();
		}
		ans[i] = a[i][c[i]];
	}
	m = rd();
	for (int i = 1; i <= m; i++) {
		for (int j = 1; j <= n; j++) {
			int x = rd();
			b[i][j] = x;
			C[i][j] = a[j][x];
		}
		crash.insert(ha(C[i]));
	} 
	if (check(ans) == false ) {
		for (int i = 1; i <= n; i++) printf("%d ", c[i]);
		return 0;
	}
 	for (int i = 1; i <= m; i++) {
 		ull res = 0, pos = 0;
		for (int j = 1; j <= n; j++) {
			if (b[i][j] > 1) {
				ull tmp = C[i][j];
				C[i][j] = a[j][b[i][j]-1];
				if (check(C[i]) == false) {
					ull rest = 0;
					for (int k = 1; k <= n; k++) rest += C[i][k];
					if (rest > res) {
						pos = j;
						res = rest; 
					}
				}
				C[i][j] = tmp;
			}
		}
		if (pos != 0 && res > rres) {
			//printf("pos == %llu res == %llu\n", pos, res);
			rres = res;
			for (int j = 1; j <= n; j++) {
				if (pos == j) ans[j] = lower_bound(a[j]+1,a[j]+c[j]+1, a[j][b[i][j]-1])-a[j];
				else ans[j] = lower_bound(a[j]+1, a[j]+c[j]+1, a[j][b[i][j]])-a[j];
			}
		}
	}
	for (int i = 1; i <= n; i++) printf("%d ", ans[i]);
	return 0;
}
上一篇:第15届黑龙江省赛 B. Bills of Paradise


下一篇:NOIP模拟64