CodeChef

题意:给定6个品牌的智能手机,从1~6编号。这里有N个智能手机,有价格pi和品牌编号bi。每个顾客喜欢给定品牌子集的智能手机,并且他准备买价格为第k大的手机。你会有Q个询问,每个询问给出顾客喜欢的品牌子集和k,输出这个手机价格。

分析:品牌个数很小,我们可以考虑(状态压缩),我们把所有子集的组合用二进制形式表示,然后预处理出每个组合的所有品牌的手机价格,并添加至这个f[(1 << 6)][N]数组中,然后询问的时候,直接查询(f[偏好的子集][k])

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;
const int N = 100005;
int p[N], b[N];

pair<int, int> c[N];

int f[(1 << 6)][N];

int main()
{
	int n, q;
	scanf("%d%d", &n, &q);

	for (int i = 0; i < n; ++i) cin >> p[i];
	for (int i = 0; i < n; ++i) cin >> b[i];
	for (int i = 0; i < n; ++i) c[i] = { p[i], b[i] };

	//从小到大
	sort(c, c + n);

	for (int i = 0; i < (1 << 6); ++i)
	{
		int cnt = 0;
		for (int j = n - 1; j >= 0; --j)
		{
			//获取编号
			int id = c[j].second - 1;
			if ((i >> id) & 1) f[i][cnt++] = c[j].first;
		}
	}

	while (q--)
	{
		int m, k;
		cin >> m >> k;

		int d = 0;

		for (int i = 0; i < m; ++i)
		{
			int x;
			cin >> x;
			d |= (1 << (x - 1));
		}
		if (f[d][k - 1] == 0)
			cout << -1 << endl;
		else
			cout << f[d][k - 1] << endl;

	}

	return 0;
}
原文地址:https://www.cnblogs.com/pixel-Teee/p/13220713.html