题意:给定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;
}