[PKUSC2018]真实排名
题目描述
小 C 是某知名比赛的组织者,该比赛一共有 \(n\) 名选手参加,每个选手的成绩是一个非负整数,定义一个选手的排名是:成绩不小于他的选手的数量(包括他自己)。例如如果 \(3\) 位选手的成绩分别是 \([1 , 2 ,2]\) ,那么他们的排名分别是 \([3,2,2]\) 。
拥有上帝视角的你知道所有选手的实力,所以在考试前就精准地估计了每个人的成绩,设你估计的第 \(i\) 个选手的成绩为\(A_i\),且由于你是上帝视角,所以如果不发生任何意外的话,你估计的成绩就是选手的最终成绩。
但是在比赛当天发生了不可抗的事故(例如遭受到了外星人的攻击),导致有一些选手的成绩变成了最终成绩的两倍,即便是有上帝视角的你也不知道具体是哪些选手的成绩翻倍了,唯一知道的信息是这样的选手恰好有 \(k\) 个。
现在你需要计算,经过了不可抗事故后,对于第 \(i\) 位选手,有多少种情况满足他的排名没有改变。
由于答案可能过大,所以你只需要输出答案对 \(998244353\) 取模的值即可。
输入格式
第一行两个正整数 \(n,k\)
第二行 \(n\) 个非负整数 \(A_1..A_n\)
输出格式
输出 \(n\) 行,第 \(i\) 行一个非负整数 \(ans_i\),表示经过不可抗事故后,第 \(i\) 位选手的排名没有发生改变的情况数。
样例 #1
样例输入 #1
3 2
1 2 3
样例输出 #1
3
1
2
提示
对于 \(10\%\) 的数据,有 \(1\leq n\leq 15\)
对于 \(35\%\) 的数据,有 \(1\leq n\leq 10^3\)
另有 \(10\%\) 的数据,满足每个人的成绩都互不相同
另有 \(10\%\) 的数据,满足 \(0\leq A_i\leq 10^5\)
另有 \(10\%\) 的数据,满足 \(k=85\),\(0\leq A_i\leq 600\)
对于\(100\%\)的数据,有\(1\leq k < n\leq 10^5\),\(0\leq A_i\leq 10^9\)
考虑把所有 \(a\) 排序后处理。
\(a\) 数组中,如果第 \(i\) 个数不乘2,那么大于等于 \(a_i\) 的数随便乘,小于 \(a_i\) 的,要满足 \(2a_j<a_i\) 的 \(a_j\) 才可以给 \(a_j\) 乘2.
如果第 \(i\) 个数乘了 2,那么 所有满足 \(a_i\le a_j,2a_i>a_j\) 的数都要乘个 2,其余随便。
用双指针维护即可。
小细节:
- 注意双指针时 while 里面两个都不去等。
- 注意处理组合数时不要把 \(k\) 减出界。
- 注意 \(2\times 0=0\),所以要特判 \(a_i=0\)
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,P=998244353;
int n,k,a[N],f[N],id[N],inv[N],ans[N],iv[N],l,r;
int cmp(int x,int y)
{
return a[x]<a[y];
}
int calc(int x,int y)
{
// if(x==1&&y==0)
// printf("%d %d %d\n",f[x],iv[y],iv[x-y]);
return 1LL*f[x]*iv[y]%P*iv[x-y]%P;
}
int main()
{
iv[0]=inv[1]=iv[1]=f[0]=f[1]=1;
scanf("%d%d",&n,&k);
for(int i=2;i<=n;i++)
{
f[i]=1LL*f[i-1]*i%P;
inv[i]=1LL*(P-P/i)*inv[P%i]%P;
iv[i]=1LL*iv[i-1]*inv[i]%P;
}
// printf("%d\n",calc(2,2));
for(int i=1;i<=n;i++)
scanf("%d",a+i),id[i]=i;
sort(id+1,id+n+1,cmp);
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
{
r=max(r,i);
if(i^1&&a[i]==a[i-1])
{
ans[id[i]]=ans[id[i-1]];
continue;
}
// printf("%d %d\n",l,r);
while(a[l+1]*2<a[i])
++l;
ans[id[i]]=calc(l+n-i,k);
while(r^n&&a[i]*2>a[r+1])
++r;
// printf("%d %d\n",i-1+n-r,k-r+i-1);
if(r-i+1<=k)
(ans[id[i]]+=calc(i-1+n-r,k-r+i-1))%=P;
// printf("%d %d\n",l,r);
}
for(int i=1;i<=n;i++)
printf("%d\n",ans[i]);
}
标签:10,成绩,洛谷,int,leq,选手,排名,P5368
From: https://www.cnblogs.com/mekoszc/p/17113657.html