Educational Codeforces Round 28 F. Random Query 期望(贡献思想)

来源:互联网 发布:华彩人生软件 编辑:程序博客网 时间:2024/05/21 14:52

官方题解。。

846F - Random Query

For each index i we will find the number of pairs (l, r) (before swapping) such that i is the first occurence of ai in the chosen segment. Let f(i) be previous occurence of ai before i (if i is the first occurence, then f(i) = 0 if we suppose the array to be 1-indexed). Let’s find the number of pairs such that l ≤ r, and then multiply it by 2 and subtract 1 for this index. l has to be in segment (f(i), i], and r has to be in segment [i, n], so the number of ways to choose this pair is (i - f(i))(n - i + 1).

The value we receive as the sum of these values over all segments is the total number of distinct elements over all pairs (l, r), so we need to divide it by the number of these pairs.

题意:

给你n个数的序列,你可以随机选一个区间(l,r) (if l > r swap(l,r)). 区间的价值定义为区间不同数的个数.现在问你选择区间的期望价值是多少.

思路:

期望 = 总价值/区间总数. 区间总数为 n*n.

现在考虑怎么计算每个区间的价值.因为每有一个值,对区间的价值贡献就为1(假设所有数都不重复的情况下).所以我们

就考虑当前这个数对多少区间有贡献,那么肯定是跨越它的区间了,我们可以从反面来考虑,假设每个数对所有区间都有贡献,那么贡献

为n*n ,没有跨越它的区间就是他的左面和右面.我们要考虑减掉这一部分,但是如果有重复数的话,那么未出现该数的区间就是所有

重复数的两两中间那一部分了,其余的部分都出现了该数,该数都有价值.

所以该题就变成了我们把所有相同数的下标存在一起然后计算就可以了,但是为了不漏掉头和尾,这里我们将每个数里都存个

0和n+1,保证计算正确性.

#include<bits/stdc++.h>using namespace std;#define maxn 1001000#define ll long longint las[maxn];int n;ll tot,now;int main(){    scanf("%d",&n);    for(int i=1;i<=n;++i)    {        int x;        scanf("%d",&x);        if(las[x]) now-=las[x];        tot+=now+i-1;        now+=i; las[x]=i;    }    tot<<=1; tot+=n;    double ans=tot*1.0/(1LL*n*n);    printf("%.10lf\n",ans);    return 0;}
阅读全文
0 0
原创粉丝点击