CF1619D New Year's Problem
题目大意
\(\rm Vlad\) 有 \(n\) 个朋友,每个朋友需要且仅需要 \(1\) 个礼物。有 \(m\) 家礼物商店,如果在第 \(i\) 个商店中为朋友 \(j\) 买礼物,朋友 \(j\) 将获得 \(p_{i,j}\) 的快乐值。
由于时间紧迫,\(\rm Vlad\) 最多只会在 \(n-1\) 家不同的商店中买礼物。请你使每位朋友能获得的快乐值中的最小值最大。
题目分析
看到类似求“最大值最小”“最小值最大”的题马上想到二分答案。
所以我们二分快乐值。
对于每一个快乐值,我们怎么判断它不可行呢?
两种情况:有一个人没有礼物和所有店都只能满足一个人(因为是选择 \(n-1\) 家店,所以可行必定至少有一家店满足的人数大于等于 \(2\))。
一个小 \(\rm trick\):
遇到题目中这种 \(n\times m\) 的和不超过 \(10^5\) 的题目,开二维数组的话,\(n,m\) 的具体范围未知,可能会导致 \(\verb!MLE!\)。
解决办法有两个:
用 \(\mathbf{vector}\);
压缩成一维数组。
也就是:
a[(i-1)*m+j]=a[i][j]可以有效减少内存。
代码
//2022/1/11
const int ma=1e5+5;
int a[ma];
int T,n,m;
inline bool check(int now)
{
for(register int i=1;i<=m;i++)
{
bool mark=true;
for(register int j=1;j<=n;j++)
{
if(a[(j-1)*m+i]>=now)
{
mark=false;
}
}
if(mark==true)//一个人的礼物在哪家店都买不到
{
return false;
}
}
for(register int i=1;i<=n;i++)
{
int num(0);
for(register int j=1;j<=m;j++)
{
if(a[(i-1)*m+j]>=now)
{
num++;
}
}
if(num>=2)//有一家店至少能同时买到至少两个人的礼物
{
return true;
}
}
return false;
}
inline int binary()
{
int l=1,r=1e9;
//枚举快乐值
while(l<r)
{
int mid=(l+r+1)>>1;
if(check(mid)==true)
{
l=mid;
}
else
{
r=mid-1;
}
}
return l;
}
inline void solve()
{
mst(a,0);
n=read(),m=read();
for(register int i=1;i<=n;i++)
{
for(register int j=1;j<=m;j++)
{
a[(i-1)*m+j]=read();
}
}
printf("%d\n",binary());
}
int main(void)
{
T=read();
while(T--)
{
solve();
}
return 0;
}

浙公网安备 33010602011771号