Educational Codeforces Round 117
E.Messages
由于 1 ≤ k i ≤ 20 1\leq ki \leq20 1≤ki≤20,故我们只需要枚举将多少条消息置顶,假设我们将 x x x条消息置顶,则我们可以得出第 i i i个学生对置顶消息每条消息 m i m_i mi的贡献,当消息 m i m_i mi没有被置顶,那么这条消息的贡献为0;当我们在置顶消息中选择一条消息的概率为 1 x \frac{1}{x} x1,那么第 i i i个学生对置顶的消息 m i m_i mi的贡献为 m i n ( k i , x ) x \frac{min(k_i,x)}{x} xmin(ki,x),最后我们只需要将置顶消息的贡献排序,取出前x大贡献的消息置顶,取出最大的贡献答案即为题目要求。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 998244353;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1.0);
#define rep(i,a,b) for(int i=a;i<=b;i++)
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = a * res % mod; b >>= 1; a = a * a % mod; } return res; __gcd(a, b);}
inline ll read() {ll x=0,f=1; char c=getchar();while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;}
inline void write(ll x){if (x < 0) x = ~x + 1, putchar('-');if (x > 9) write(x / 10);putchar(x % 10 + '0');}
int n;
struct node{
int sum,k;
bool operator<(const node & a)const{
return sum>a.sum;
}
}a[200005];
int m[200005],k[200005];
void solve(){
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%d%d",&m[i],&k[i]);
double maxn=0.0;
vector<int>ans;
for(int i=1;i<=20;i++){
for(int j=0;j<=200000;j++)a[j]={0,j};
for(int j=0;j<n;j++){
if(k[j]<i)a[m[j]].sum+=k[j];
else a[m[j]].sum+=i;
}
sort(a,a+200001);
double res=0;
vector<int>temp;
for(int j=0;j<i;j++){
res+=a[j].sum;
temp.emplace_back(a[j].k);
}
res/=i;
if(res>maxn){
maxn=res;
ans=temp;
}
}
printf("%d\n",ans.size());
for(auto i:ans)printf("%d ",i);
printf("\n");
}
int main() {
int t;
//scanf("%d",&t);while(t--)
solve();
return 0;
}