逆序对
Posted kstt
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逆序对相关的知识,希望对你有一定的参考价值。
依旧还是TT的评测
题目描述
有一个1 ? n的排列,你会依次进行m次操作,第i次操作表示为(x i , y i ),交换以这两个
值为下标的元素,每次操作有一半的概率成功,你需要求出最后序列的逆序对的期望个数。
tips:期望值
输入
输入文件 inversion.in。
第一行两个数n, m。
第二行n个数表示初始的排列。
接下来m行,每行两个数表示x i , y i 。
输出
输出文件 inversion.out。
一个实数表示答案,四舍五入保留到小数点后 8 位,要求绝对误差不超过 10 -6 。
(评测时开启实数比较模式)
样例输入
4 3
1 3 2 4
1 2
2 3
1 4
样例输出
3.00000000
数据说明
30%: n ≤ 10, m ≤ 20
100%: n ≤ 1000, m ≤ 1000
思路
1.我们用一个f[i][j]数组储存i位置上的值和j位置上的值之间是否存在逆序对
2.然后输入我们要交换的2个位置x,y,用for循环来计算出他对每个的影响,因为每次操作有50%的成功几率,那么原来的f[x][i]和f[y][i]之间要*0.5
即
f[x][i]=f[y][i]=0.5*(f[x][i]+f[y][i]);
那么
f[i][x]=f[i][y]=1-f[x][i];
由于是x,y互换
所以f[x][y]=f[y][x]=0.5;
3.然后我们所需要做的就是把它们加起来,求出最后的期望值(期望个数)
代码
#include<bits/stdc++.h> using namespace std; int n,m; int a[1050]; double ans=0; double f[1010][1010]; int scan()//借鉴GQL的更新快读,please remember!! { int as=0; bool y=1; char c=getchar(); while(c!=‘-‘&&(c>‘9‘||c<‘0‘)) c=getchar(); if(c==‘-‘) y=0,c=getchar(); while(c>=‘0‘&&c<=‘9‘) as=(as<<3)+(as<<1)+(c^‘0‘),c=getchar(); return y?as:-as; } int main() { n=scan(); m=scan(); for(int i=1;i<=n;i++) a[i]=scan(); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { f[i][j]=a[i]>a[j];//f[i][j]表示i和j之间是否存在逆序对 // cout<<i<<" "<<j<<" "<<f[i][j]<<endl; } } while(m--) { int x=scan();//输入要交换的2个位置 int y=scan(); for(int i=1;i<=n;i++)//!!!!,x,y是2个位置 { f[x][i]=f[y][i]=(double)0.5*(f[x][i]+f[y][i]); f[i][x]=f[i][y]=(double)1-f[x][i]; } f[x][y]=f[y][x]=0.5; } ans=0; for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { ans+=(double)f[i][j]; } } printf("%.8lf",ans); return 0; }
以上是关于逆序对的主要内容,如果未能解决你的问题,请参考以下文章