您的位置:首页 > 产品设计 > UI/UE

Educational Codeforces Round 28 Random Query 思维

2017-09-07 14:28 369 查看
题目链接

题意:

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

思路:

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

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

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

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

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

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

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

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn = 1e6+10;
vector<int>vt[maxn];
ll n;
int main()
{
cin>>n;
for(int i=1;i<maxn;++i)
vt[i].push_back(0);
for(int i=1;i<=n;++i)
{
int b;
scanf("%d",&b);
vt[b].push_back(i);
}
for(int i=1;i<maxn;++i)
vt[i].push_back(n+1);
ll tmp = 0;
ll ans = n*n;
for(int i=1;i<maxn;++i)
{
if(vt[i].size()==2)
continue;
tmp += ans;
for(int j=1;j<(int)vt[i].size();j++)
{
ll tt = vt[i][j]-vt[i][j-1]-1;
tmp -= tt*tt;
}
}
printf("%.12f\n",tmp*1.0/ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: