[AGC018B] Sports Festival
题目大意
有 个人 个活动,告诉你每一个人对于活动喜欢程度的排序,你可以鸽掉一些活动。如果一个最喜欢的活动被鸽了,那么他就会参加次喜欢的,依次类推直到参加为止。
求参加人数最多的那个项目,参加人数最少是多少。
思路
做法:
首先模拟出每一个活动的参加人数,依次将人数最多的活动鸽掉,一遍鸽一遍统计最小值。
理由:
假设你已经鸽掉了一些活动,你么现在总能找到一个参加人数最多的项目,假设这个项目是第 个项目。如果将非 的项目鸽掉,那么参加第 个项目的人就并不会减少反而还会增加,这对将整体的最大值减小是没有任何效果的。
假设你鸽掉了第 个项目,那么你肯定就又可以找到一个参加人数是最多的项目,假设是第 个项目。那么如果不鸽掉第 个项目与前面鸽掉第 个项目的效果其实是一样的。所以在这次操作就只能将 鸽掉,否则就没有意义。
AC Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=305;
int n,m,a[N][N],s[N],top[N],ans=1e18;
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
top[i]=1;
}
}
for(int i=1;i<=n;i++){
s[a[i][1]]++;
}
for(int i=1,p,mmax;i<=m;i++){
mmax=0;
for(int j=1;j<=m;j++){
if(s[j]>mmax){
mmax=s[j];
p=j;
}
}
ans=min(ans,mmax);
s[p]=-1;
for(int j=1;j<=n;j++){
bool flag=0;
while(s[a[j][top[j]]]==-1){
top[j]++;
flag=1;
}
if(flag){
s[a[j][top[j]]]++;
}
}
}
cout<<ans<<'\n';
return 0;
}