CF846F Random Query
CF846F Random Query
题意
给定一个数列A,随机选取两个值l,r(等概率,可以相等),进行以下操作: if l > r : swap(l,r) 对数列A中l,r区间内的数去重得到数列B 求数列B的期望大小。
题解
显然每次l和r都是随机的直接求不好求
但是每个数最后对答案的贡献是一样的
考虑期望的可加性,只需要求每个数最后留在数列中的概率
显然如果当前这个数是这个值第一次出现他就不会被删掉
预处理出每个数相同的值出现的位置,那么 L 应该在这个值上一次出现的位置到当前位置间,R在后面
直接求就行了
#include<bits/stdc++.h> #define LL long long using namespace std; inline LL read() { LL f = 1 , x = 0; char ch; do { ch = getchar(); if(ch=='-') f=-1; } while(ch<'0'||ch>'9'); do { x=(x<<3) + (x<<1) + ch - '0'; ch = getchar(); }while(ch>='0'&&ch<='9'); return f*x; } const int MAXN = 1000000 + 10; int n; int a[MAXN]; int Last[MAXN],L[MAXN]; double ans; int main() { n = read(); for(int i=1;i<=n;i++) a[i] = read(); for(int i=1;i<=n;i++) { L[i] = Last[a[i]]; Last[a[i]] = i; } for(int i=1;i<=n;i++) { ans += 2.0 * (n - i + 1) * (i - L[i])-1; } ans /= 1.0*n*n; printf("%.4f",ans); }