有一个比赛已经有 n 个人参加,并且互相之间已经进行了比赛
每一个人都有一个得分用于最后排名
你作为第 n + 1 个参赛者,需要与之前的每一个人打一场比赛,初始得分为 0
对于每场比赛,有两个人参加,不会存在平局,胜者得分增加 1,败者得分不变
最后按照得分从高到低来排名,假设有人与你最终得分相同
那么如果那个人曾经输给了你就会排在你后面,否则会排在你的前面
如果你赢了某个人,就需要消耗相应的 RP 值
现在你可以决定赢那些人,求最少需要消耗多少 RP 值才能到前k名
50分做法:还是枚举二进制串……居然有50分
100分做法:
这个满分做法是真的玄学,我们需要分三种情况讨论来贪心求解:
- 如果一个人的胜场和自己相同或者刚好少1,不打就会被挤下去,打了就可以升一位
- 如果一个人的胜场比自己多,打不打都没什么差异……
- 如果一个人的胜场比自己少2或者更多,那就可以不用打了
然后贪心就好
代码:
#include<bits/stdc++.h>
#define ll long long
#define maxn 2505
using namespace std;
int T,n,k,gol,num;
ll ans;
bool used[maxn];
struct People
{
int p, e;
}p[maxn];
bool cmp1(People x, People y) {return x.p > y.p;}
bool cmp2(People x, People y) {return x.e < y.e;}
bool check()
{
int res=0;
for(register int i=1;i<=n;++i)
if(p[i].p>n) res++;
return res>=k;
}
ll work1()
{
ll ret=0;
int cnt=gol,num1=0,num2=num;
for(register int i=1;i<=n;++i)
{
used[i]=0;
if(p[i].p==gol-1) ++num1;
}
for(register int i=1;i<=n&&num2;++i)
{
if(p[i].p==gol)
{
ret=ret+p[i].e;
used[i]=1;
--cnt;
--num2;
}
}
for(register int i=1;i<=n&&num1;++i)
{
if(!used[i]&&(p[i].p==gol||p[i].p==gol-1))
{
ret=ret+p[i].e;
used[i]=1;
--cnt;
--num1;
}
}
for(register int i=1;i<=n&&cnt;++i)
{
if(!used[i])
{
ret=ret+p[i].e;
--cnt;
}
}
return ret;
}
ll work2()
{
ll ret=0;
int num2=num,cnt=gol+1;
for(register int i=1;i<=n;++i) used[i]=0;
for(register int i=1;i<=n&&num2;++i)
{
if(p[i].p==gol||p[i].p==gol+1)
{
used[i]=1;
ret=ret+p[i].e;
--cnt;
--num2;
}
}
for(register int i=1;i<=n&&cnt;++i)
{
if(!used[i])
{
ret=ret+p[i].e;
--cnt;
}
}
return ret;
}
ll work3()
{
ll ret=0;
for(register int i=1;i<=gol+2;++i)
ret=ret+p[i].e;
return ret;
}
template<class T>inline void read(T &res)
{
char c;T flag=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}
int main()
{
freopen("tournament.in","r",stdin);
freopen("tournament.out","w",stdout);
read(T);
while(T--)
{
read(n);read(k);
for(register int i=1;i<=n;++i) scanf("%d%d",&p[i].p,&p[i].e);
if(k==n+1)
{
printf("0
");
continue;
}
if(check())
{
printf("-1
");
continue;
}
sort(p+1,p+n+1,cmp1);
gol=p[k].p;
num=1;
while(p[k+num].p==p[k].p&&k+num<=n) ++num;
sort(p+1,p+n+1,cmp2);
ans=min(work1(),min(work2(),work3()));
printf("%lld
",ans);
}
return 0;
}