Codeforces Round #388 (Div. 2) 749E(巧妙的概率dp思想)

题目大意

给定一个1到n的排列,然后随机选取一个区间,让这个区间内的数随机改变顺序,问这样的一次操作后,该排列的逆序数的期望是多少

首先,一个随机的长度为len的排列的逆序数是(len)*(len-1)/4,这是显然的,因为每种排列倒序一遍就会得到一个新序列,逆序数是len*(len-1)/2 - x(x为原排列的逆序数)

所以我们只需要把所有n*(n-1)/2的区间每种情况都随机化一遍再求逆序对,然后把这个值求和,就可以得到答案了

但是如果用朴素做法,那么复杂度是n^2的

考虑dp[x]表示以x为右端点的所有区间的逆序对数

dp[x] = sigma(dp[1~(x-1)]) + f[x]

f[x]表示x这个数对其以x为右端点所有区间的逆序对数所做的贡献,简单说,就是加了x以后,逆序对增加的个数

那么显然出现在第一位的数的贡献为1,而在第二位的数贡献为2,然后把相应的值加到权值线段树里

就可以统计出来所有的dp[x]了

最终答案就是 原序列的逆序对数-(Sum(dp[x])-Sum(所有区间随机化))/区间个数

PS:精度比较坑,中间整数运算尽量用long long,最后再用long double

#include <iostream>
#include <cstring>
#include <cstdio>
#include <iomanip>
using namespace std;
typedef long double ld;
const int maxn = 111111;
long long tree[maxn*4];
void Insert(int o, int l, int r, int k, int v)
{
    if(l == r)
    {
        tree[o] = v;
        return;
    }
    int mid = (l+r)>>1;
    if(k <= mid) Insert(o*2, l, mid, k, v);
    else Insert(o*2+1, mid+1, r, k, v);
    tree[o] = tree[o*2] + tree[o*2+1];
}

long long Query(int o, int l, int r, int L, int R)
{
    if(L <= l && r <= R) return tree[o];
    int mid = (l+r)>>1;
    ld ans = 0;
    if(L <= mid) ans += Query(o*2, l, mid, L, R);
    if(R > mid) ans += Query(o*2+1, mid+1, r, L, R);
    return ans;
}
int n, x, a[maxn], f[maxn];
int main()
{
    cin>>n;
    ld ans = 0;
    for(int i = 1; i <= n; i++) cin>>a[i], f[a[i]] = i;
    for(int i = 1; i <= n; i++)
    {
        ans += Query(1, 1, n, a[i], n);
        Insert(1, 1, n, a[i], 1);
    }
    ans *= ((long long)n*(n+1));
    memset(tree, 0, sizeof(tree));
    long long last = 0;
    for(int i = 1; i <= n; i++)
    {
        ans -= (last + Query(1, 1, n, a[i], n));
        last = last + Query(1, 1, n, a[i], n);
        Insert(1, 1, n, a[i], f[a[i]]*2);
    }
    for(int i = 1; i <= n; i++)
        ans += ((long long)(n-i+1)*i*(i-1)/2);x`
    ans /= ((long long)n*(n+1));
    cout<<setprecision(15)<<ans<<endl;
}
时间: 2024-12-19 01:35:41

Codeforces Round #388 (Div. 2) 749E(巧妙的概率dp思想)的相关文章

Codeforces Round #417 (Div. 2) B. Sagheer, the Hausmeister(DP)

题目链接:Codeforces Round #417 (Div. 2) B. Sagheer, the Hausmeister 题意: 有n层楼,每层有m个房间,每层的两边是楼梯. 现在有一个人站在左下角,这个人必须将这一层的灯关闭后才能去另外一层. 每移动一次需要1分钟,问关闭所有灯需要多少时间. 题解: 考虑DP[i][j]表示当前已经关闭了第i层全部的灯,j=0时表示在这一层的最左边,j=1时表示在这一层的最右边. 然后推上去就行了.最后讨论一下特殊情况. 1 #include<bits/

Codeforces Round #360 (Div. 2) D 数学推导 E dp

Codeforces Round #360 (Div. 2) A  == B  水,但记一下: 第 n 个长度为偶数的回文数是  n+reverse(n). C    dfs 01染色,水 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i

Codeforces Round #399 B 思维 C 模拟 D 概率dp E SG博弈

Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined)B. Code For 1 题意:数n,不断拆分为 n/2, n&1, n/2,直到都为0或1.求区间[l, r]有多少个1. tags:画一画很容易看出来,类似dfs中序遍历. //#399 B #include<bits/stdc++.h> using namespace std; #pragma comment(linker, &quo

Codeforces Round #388 (Div. 2) C. Voting

题意:有n个人,每个人要么是属于D派要么就是R派的.从编号1开始按顺序,每个人都有一次机会可以剔除其他任何一个人(被剔除的人就不在序列中也就失去了剔除其他人的机会了):当轮完一遍后就再次从头从仅存的人中从编号最小开始重复执行上述操作,直至仅存在一派,问最后获胜的是哪一派? 并且,题目假设每个人的选择是最优的,即每个人的操作都是会尽可能的让自己所属的派获胜的. 题解: 一开始看到说每个人的操作都会是最优的还以为是个博弈(=_=),,,仔细琢磨了下样例发现并不用,只要贪心模拟就行了.贪心的策略并不难

Codeforces Round #388 (Div. 2) D

There are n people taking part in auction today. The rules of auction are classical. There were n bids made, though it's not guaranteed they were from different people. It might happen that some people made no bids at all. Each bid is define by two i

Codeforces Round #388 (Div. 2) C

There are n employees in Alternative Cake Manufacturing (ACM). They are now voting on some very important question and the leading world media are trying to predict the outcome of the vote. Each of the employees belongs to one of two fractions: depub

Codeforces Round #388 (Div. 2) B

Long time ago Alex created an interesting problem about parallelogram. The input data for this problem contained four integer points on the Cartesian plane, that defined the set of vertices of some non-degenerate (positive area) parallelogram. Points

Codeforces Round #388 (Div. 2) A

Bachgold problem is very easy to formulate. Given a positive integer n represent it as a sum of maximum possible number of prime numbers. One can prove that such representation exists for any integer greater than 1. Recall that integer k is called pr

Codeforces Round #245 (Div. 1) B. Working out (简单DP)

题目链接:http://codeforces.com/problemset/problem/429/B 给你一个矩阵,一个人从(1, 1) ->(n, m),只能向下或者向右: 一个人从(n, 1) ->(1, m),只能向上或者向右.必须有一个相遇点, 相遇点的值不能被取到, 问两个人能得到的最大路径和是多少? dp[i][j]:表示从一个点出发的最大值:先预处理从(1,1) (1,m) (n,1) (n,m)四个点出发的4个dp最大值.然后枚举所有的点,但是这个点不能在边缘,考虑枚举点不够