CodeForces 1619D New Year's Problem
New Year's Problem
有n个人,m个商店,每个商店有n个物品,也有对应的\(a_i\),代表第i个人对这个物品的好感度。现在要求进入n-1个商店,为每个人购买一件物品,使得最后n个人中,获得物品的最低好感度最高
二分
一开始以为是贪心或者排序,没往二分上面想,想了半天的暴力也没想到有什么办法能够找到n-1家商店的情况
后来有人说是二分的时候,也没有什么头绪,因为不知道如何去检查一个答案是否正确
这里给出二分能够完成的原因:假设现在的值是X,当X大于最后的答案的时候,必然是不成立的;当X小于最后答案的时候,是可以成立的,因此他是一个单调的函数,可以使用二分来查找答案
如何检查答案是否正确:
-
因为是要在n-1个商店里面找因此首先得满足,至少有一家商店的商品的好感度大于等于X
-
因为是每个人都要收到礼物,因此每个人至少能收到一件大于等于X好感度的礼物
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 1e5 + 10;
vector<int>gra[maxn];
int num[maxn];
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
int m, n;
scanf("%d%d", &m, &n);
for(int i=0; i<m; i++)
gra[i].clear();
for(int i=0; i<m; i++)
{
for(int j=0; j<n; j++)
{
int x;
scanf("%d", &x);
gra[i].push_back(x);
}
}
int l = 1, r = 1e9 + 10;
while(l < r)
{
int mid = l + r >> 1;
bool flag = false;
for(int i=0; i<n; i++)
num[i] = 0;
for(int i=0; i<m; i++)
{
int cnt = 0;
for(int j=0; j<n; j++)
{
if(gra[i][j] >= mid)
{
cnt++;
num[j]++;
}
}
if(cnt >= 2)
flag = true;
}
for(int i=0; i<n; i++)
if(num[i] == 0)
flag = false;
if(flag)
l = mid + 1;
else
r = mid;
}
printf("%d\n", l - 1);
}
return 0;
}