NWERC 2019 A

A. Average Rank

The National Weekly Escape Room Challenge (NWERC) is a long-running competition held in Eindhoven. Every week a new escape room is presented, and anyone who completes it in their first attempt gains one point.c++

At the end of each week, competitors are ranked by the total number of points accumulated so far, highest first. In the case of a tie, they share the same rank. In other words, the rank of a competitor is one more than the number of people with a strictly larger number of points.git

In total there have been \(n\) participants in the contest, and the contest has been going for w weeks. For each week you are given a list of the competitors that gained a point that week. Your task is to calculate the average rank during the w-week competition for each competitor.
The figure illustrates the score progression in the third sample.優化

Input
The input consists of:spa

One line with two integers \(n\) and \(w\) (\(1≤n,w≤3⋅10^5\)), the number of competitors and the number of weeks. The competitors are numbered from \(1\) to \(n\).
\(w\) lines (one for each week), each containing an integer \(k\) (\(0≤k≤n\)) followed by \(k\) distinct integers \(c_1,…,c_k\) (\(1≤c_i≤n\) for all \(i\)), indicating that the \(k\) competitors \(c_1,…,c_k\) each gained a point that week.
The total number of points awarded is at most 1 million.code

Output
Output \(n\) lines, the ith of which contains the average rank of the \(ith\) competitor during the \(w\)-week competition. Your answers should have an absolute or relative error of at most \(10^{−6}\).ip

題解

這題說實話思惟量很大。ci

其實咱們要先想到,操做總數小於一百萬,也就是說,對於一個參賽者分數\(+1\), 受到修改的,只有和他同分的人以及他本身,修改一次,與他同分的人加一,他本身的排名也會隨之變化。get

而後咱們考慮每一個人的平均排名,實際上就是每週的排名之和。input

假設咱們暴力處理的話, 效率就是\(O(n*w)\).it

考慮優化這個過程。

類比修改線段樹的\(lazy_tag\), 咱們對於每次\(+1\)修改的,利用差分的思想,到用到的時候再算進去。

說實話有點難想。

Code

#include<bits/stdc++.h>
#define _(d) while(d(isdigit(ch=getchar())))
#define rep(i,a,b) for(int i=a;i<=b;i++)
template<class T>void g(T&t){T x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=x*10+ch-48;t=f*x;}
using namespace std;
const int N = 1e6 + 4;
typedef long long ll;
ll n, w, now[N], pre[N], cnt[N], p[N], sum[N];
int main(){
	g(n), g(w);
	cnt[1] = n;
	rep( i, 0, n ) sum[i] = w, p[i] = 1;
	rep( i, 1, w ){
		int Len; g(Len);
		while( Len-- ){
			int x; g(x);
			sum[ x ] += now[ p[x] ] - pre[ x ];
			now[ p[x] ] += ( w - i + 1 );
			cnt[ p[x] ] --;
			p[ x ] ++;
			sum[ x ] -= cnt[ p[x] ] * ( w - i + 1 );
			pre[ x ] = now[ p[x] ];
			cnt[ p[x] ]++;
		}
	}
	rep( i, 1, n ){
		sum[i] += now[ p[i] ] - pre[i];
		printf("%.11lf\n",1.0 * sum[i] / ( 1.0 * w ));
	}
	return 0;
}
相關文章
相關標籤/搜索