Description:
在三场考试中,有nnn为选手,现在已知每位选手的第一场和第二场的分数,并且知道若选手AAA的第一场和第二场的分数都严格大于选手BBB,则AAA的第三场的分数一定大于BBB,以及每场的分数为0~650。求每位选手最后总分的最高排名和最低排名。
n≤500000n\le50 0000n≤500000
Solution:
- 模拟小数据,发现,满足题意的严格大于的选手AAA的排名一定比BBB高,小于同理,即AAA的最高排名-1,BBB的最低排名+1。
- 由于分数比较小,那么我们可以直接用二维前缀和来维护。
- 但是第三场的分数最高为650。考虑AAA最高排名,如果给了AAA 650分,给大于AAA的人650分,给其他人0分,可能有其他人总分大于等于AAA的。
- 其实不会大于,只会等于,因为既然那个人不大于AAA,最多可能是有一场等于AAA,有一场为650。
- 而AAA那一场最低为0,也就是两人之前的分差最多为650。那么加上第三场后两人恰好相等。同理,考虑最低排名,给$A$0分,给其他人650分,也会有人和A相等。
- 由于分数相同取高位,最高排名不用管,只需要在最低排名判断,如果AAA有一场为650,那么排名就要减去另一场相等,这一场为0的人数。
Code:
#include<bits/stdc++.h>
using namespace std;
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
#define SREP(i,f,t) for(int i=(f),i##_end_=(t);i<i##_end_;++i)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;--i)
#define ll long long
template<class T>inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
template<class T>inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
template<class T>inline void Rd(T &x){
x=0;char c;int f=1;
while((c=getchar())<48)if(c=='-')f=-1;
do x=(x<<1)+(x<<3)+(c^48);
while((c=getchar())>47);
x*=f;
}
const int N=5e5+2,M=655;
int n;
int A[N],B[N];
int sum1[M][M],sum2[M][M];
int main(){
// freopen("coci.in","r",stdin);
// freopen("coci.out","w",stdout);
Rd(n);
REP(i,1,n) {
Rd(A[i]),Rd(B[i]);
sum1[A[i]][B[i]]++;
sum2[A[i]][B[i]]++;
}
REP(i,0,M-5) REP(j,0,M-5){
if(i>0) sum1[i][j]+=sum1[i-1][j];
if(j>0) sum1[i][j]+=sum1[i][j-1];
if(i>0 && j>0) sum1[i][j]-=sum1[i-1][j-1];
}
REP(i,1,n){
int Mx=1+n-sum1[650][B[i]]-sum1[A[i]][650]+sum1[A[i]][B[i]];
int Mn=n-((!A[i] || !B[i])?0:sum1[A[i]-1][B[i]-1]);
if(A[i]==650) Mn-=sum2[0][B[i]];
if(B[i]==650) Mn-=sum2[A[i]][0];
printf("%d %d\n",Mx,Mn);
}
return 0;
}
本文探讨了一种基于前缀和的数据结构解决大规模比赛排名预测的问题。通过分析选手在前两轮比赛的成绩,利用二维前缀和维护选手之间的相对优势,进而计算出每位选手在最后一轮比赛后可能的最高和最低排名。特别关注了当分数相同时如何调整排名的细节。

503

被折叠的 条评论
为什么被折叠?



