题解:P11556 [ROIR 2016 Day 2] 超级跳棋

LuoXH

2025-01-10 20:38:13

Solution

题目。

题目中说“比赛结果中任何两个玩家的得分之比最多为 k”,我们假设三个玩家的得分分别为 a,b,c,且 a\leq b\leq c,因而由题意及我们刚刚设的内容得:a\leq b \leq ak,和 a\leq c \leq ak,则 \dfrac{c}{b} \leq k

(若 \dfrac{c}{b}=t>k,则 c=bt>bk,因为 a\leq b,所以 ak\leq bk,又所以 ak<bt,得 ak<c,与 c\leq ak 矛盾,因此 t\leq k)

那么由此我们可以想到一种方法:枚举 a,再计算 b,c 的个数以及三人比分的方案数。

时间复杂度 $O(n\log n)$。 代码如下:(写得比较丑,勿喷)(注意:由于$k,x_i\leq 10^9$,因此要开 long long。~~否则有分,但不多。~~) ```cpp #include<bits/stdc++.h> using namespace std; long long a[100005],n,k,b[100005],c[100005],cnt,su[100005]; int main(){ scanf("%lld%lld",&n,&k); for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); } sort(a+1,a+n+1); for(int i=1;i<=n;i++){ if(a[i]!=a[i-1]){ cnt++; b[cnt]=a[i]; c[cnt]=1; su[cnt]=su[cnt-1]; } else{ c[cnt]++; if(c[cnt]==2) su[cnt]++; } } long long ans=0; for(int i=1;i<=cnt;i++){ long long l=i,r=cnt,g=i; while(l<=r){ long long mid=l+r>>1; if(b[mid]<=b[i]*k){ g=mid; l=mid+1; } else{ r=mid-1; } } if(g==i){ if(c[i]>=3){ ans++; } continue; } ans+=(g-i)*(g-i-1)*3; ans+=(su[g]-su[i])*3; if(c[i]>=2){ ans+=3*(g-i); } if(c[i]>=3){ ans++; } } printf("%lld\n",ans); return 0; } ```