训练赛9.7
source:
2019-2020 ICPC Northwestern European Regional Programming Contest (NWERC 2019)
| Solved | A | B | C | D | E | F | G | H | I | J | K |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 7 / 11 | Ø | - | O | - | O | O | O | Ø | O | - | - |
C贪心,E 签到,但注意边界判断条件和浮点数精度误差 F并查集 I签到。
G题翻译出锅,题目中的输入的概率只可作为权值,各元素随机选取,注意判断特殊情况k==1
A
一眼为\(O(nw)\)模拟。发现总修改小于1e6,需要从此入手解题。
每次+1时,改变的排名只有输入值x和原来与x同分的人。
可以用lazy标记记录修改,用类似线段树的方式均摊复杂度。
下面结合代码变量名再理一次思路
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read(){
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar())c=='-'?f=-1:1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=1e6+1000;
int n,w;
ll lazy[maxn],num[maxn],rk[maxn],pre[maxn];
//lazy[p[i]]值为p[i]的点上次被修改的时间
//num[p[i]]值为p[i]的点,排名的累计量
//rk[p[i]]值为p[i]的点,当前排名
//pre[i]为i点上次修改后排名的累计量
ll p[maxn];//i号元素分数
ll ans[maxn];//排名总和,第i名作为第i-1名记录
signed main(){
cin>>n>>w;
for(int i=0;i<w;i++){
int k=read();
for(int j=1;j<=k;j++){
ll x=read();
num[p[x]]+=rk[p[x]]*(i-lazy[p[x]]);//1 集中处理两次修改之间的排名累计量
lazy[p[x]]=i;
rk[p[x]]++;
ans[x]+=num[p[x]]-pre[x];//2 这段时间排名的增量
p[x]++;
num[p[x]]+=rk[p[x]]*(i-lazy[p[x]]);
lazy[p[x]]=i;
pre[x]=num[p[x]];//3
//1,2,3步是精髓
}
}
for(int i=1;i<=n;i++){
num[p[i]]+=rk[p[i]]*(w-lazy[p[i]]);
lazy[p[i]]=w;
ans[i]+=num[p[i]]-pre[i];
printf("%.8lf\n",(1.0+1.0*ans[i]/w));
}
return 0;
}

浙公网安备 33010602011771号