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;
}