【题解】 牛客 2021NOIP提高组模拟赛四 A(权限题)
考虑一个人的期望排名:
\[X_i=1+\sum_{j=1}^n\frac{1}{4}\sum_{k=1}^4\frac{1}{4}\sum_{q=1}^4 P \ \ (S_{j,q}>S_{i,k})\land i\not =j
\]
\[=1+\frac{1}{16}\sum_{k=1}^4\sum_{q=1}^4\sum_{j=1}^n P \ \ (S_{j,q}>S_{i,k})\land i\not =j
\]
观察这个式子,发现可以先将所有的期望得分加入一个数组,sort一遍,然后就可以二分在 \(\log n\) 的时间内求出最后一个 \(\sum\),那这题复杂度就是 \(O(n\log n)\) 的了。
注意需要把第 \(i\) 个人自己的四个期望得分之间互相产生的贡献减去。
贴一下我刚了两个多小时的代码:
#include<bits/stdc++.h>
#define ll long long
// #define int long long
#define lc(k) k<<1
#define rc(k) k<<1|1
using namespace std;
const int MAX=1e5+10;
const int MOD=1e9+7;
inline char readchar() {
static char buf[100000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
#define readchar getchar
int res = 0, f = 0;
char ch = readchar();
for(; !isdigit(ch); ch = readchar()) if(ch == '-') f = 1;
for(; isdigit(ch);ch = readchar()) res = (res << 1) + (res << 3) + (ch ^ '0');
return f ? -res : res;
}
inline void write(int x) {
if(x<0){putchar('-');x=-x;}
if(x>9) write(x/10);
putchar(x%10+'0');
}
int a[MAX][2],qw[MAX][5],ans[MAX],jl[MAX][5];
struct node
{
int fs,id;
friend bool operator < (node x,node y)
{
return x.fs>y.fs;
}
}cj[MAX*4];
signed main()
{
int n=read();
for(int i=1;i<=n;i++)
{
a[i][0]=read();a[i][1]=read();
cj[i*4-3].fs=qw[i][1]=a[i][0]+a[i][1];
cj[i*4-2].fs=qw[i][2]=a[i][1];
cj[i*4-1].fs=qw[i][3]=a[i][0];
cj[i*4].fs=qw[i][4]=0;
cj[i*4-3].id=cj[i*4-2].id=cj[i*4-1].id=cj[i*4].id=i;
}
sort(cj+1,cj+1+n*4);
for(int i=1;i<=n;i++)
{
int sum=0;
for(int j=1;j<=4;j++)
{
int t=lower_bound(cj+1,cj+1+4*n,(node){qw[i][j],0})-cj-1;
sum+=t;jl[i][j]=t;ans[i]=sum;
}
}
for(int i=1;i<=n*4;i++)
for(int j=1;j<=4;j++)
if(i<=jl[cj[i].id][j])
ans[cj[i].id]--;
for(int i=1;i<=n;i++) printf("%.10lf\n",1.0+ans[i]/16.0);
return 0;
}