1006考试T3

1006考试T3

​ 题目大意:

​ 给定一个长度为𝑛的序列,你会在[1,𝑛]范围内随机两个正整数𝑙,𝑟,然后若有𝑙>𝑟,则交换𝑙,𝑟。你想要知道区间[𝑙,𝑟]内不同元素个数的期望。

​ 1≤𝑛≤10^6 ,1≤𝑎𝑖≤10^6

​ 期望。

​ 我们统计每个数的贡献是多少。对于一个数,我们算它可以对多少个区间产生贡献。我们记录一个\(nxt[i]\)数组,表示\(i\)这个数字下一次出现的位置在哪。

​ 对于每个数\(a[i]\),贡献就是\(i * (nxt[a[i]] - i)\), 因为只要是\(i\)左边的都可以作为左端点,\(i\)右边尚未出现下个\(a[i]\)的点地方可以作为右端点。\(l\)是可能大于\(r\)的,所以\(ans * 2\),又发现乘多了,还要减去长度为1的区间,所以\(ans - n\)。最后除以总的区间个数就好了。

#include <bits/stdc++.h>
    
using namespace std;
    
inline long long read() {
    long long s = 0, f = 1; char ch;
    while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
    for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
    return s * f;
}
    
const int N = 1e6 + 5;
int n;
long long ans;
int a[N], nxt[N], last[N];

int main() {

    n = read();
    for(int i = 1;i <= n; i++) a[i] = read();
    for(int i = n;i >= 1; i--) last[a[i]] = n + 1;
    for(int i = n;i >= 1; i--) nxt[i] = last[a[i]], last[a[i]] = i;
    for(int i = 1;i <= n; i++) ans += 1ll * i * (nxt[i] - i);
    ans = ans * 2; ans -= n;
    printf("%.3Lf", (long double) ans * (1.0 / n / n));
    
    return 0;
}
posted @ 2020-10-16 11:57  C锥  阅读(99)  评论(0编辑  收藏  举报