【Gym - 102500A】 Average Rank

1.當某個選手的分數改變時,只有原本和他分數相同的人的排名會改變。
2.每次有人得分時,時間複雜度不允許把每個原本和這個人得分相同的人的名次都更新,所以我們對得分本身更新。
3.同時,更新時對從此時開始的所有時間做貢獻,所以s_rk【分數】+=m-i+1,當想要提取一個人在當前時刻的歷史排名情況時,需要減去此時刻之後多做貢獻的部分。

#include<bits/stdc++.h>
#define rep(i,n) for(int i=1;i<=n;i++)
using namespace std;
typedef long long ll;

const int N=1e6+5;
int n,m,t,x,pts[N];
ll rk[N],rak[N],s_rk[N];
//pts[選手i] 記錄每個選手的得分
//rak[選手i] 記錄每個選手的排名和
//rk[分數p] 記錄得分數p的當前排名情況
//s_rk[分數p] 記錄得分數p的排名貢獻和

ll get_srk(int p,int i) {
    return s_rk[p]-rk[p]*(m-i+1);
}
//得到分數p的歷史排名總和

void solve() {
    rep(i,n) pts[i]=0,rak[i]=0;
    rep(i,N-1) rk[i-1]=1,s_rk[i-1]=m;
    rep(i,m) {
        scanf("%d",&t);
        rep(j,t) {
            scanf("%d",&x);
            int &p=pts[x];
            ll r=get_srk(p,i);
            ll r2=get_srk(++p,i);
            rak[x]+=r-r2;
            //r1-r2得到這個人的進步名次
            rk[p-1]++,s_rk[p-1]+=m-i+1;
        }
    }
    rep(i,n) {
        ll r=s_rk[pts[i]];
        printf("%lf\n",(r+rak[i])*1.0/m);
    }
}

int main() {
    while(~scanf("%d%d",&n,&m)) solve();
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章