首先,从后往前扫,找出第一个\(a_i\neq i\)的位置,记为\(st\)
从前往后扫,对于\(r_i<st\)的,选不选都没关系。
对于\(r_i\ge st\)的,至少有一个成功排序就会使整个序列被排序
考虑容斥,用所有情况减去\(r_i\ge st\)一个都不选的情况即可
即\(ans = 1-\prod\limits_{r_i\ge st} {1-p_i}\)
代码如下
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
int t,n,m;
int a[100005],st;
inline int read() {
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
int r[100005];
double p[100005];
int main () {
t = read();
while(t--) {
n = read();m = read();
int flag = 1;
for(int i = 1;i <= n;i++) a[i] = read();
for(int i = 1;i <= m;i++) {
scanf("%d%lf",&r[i],&p[i]);
}
for(int i = 1;i <= n;i++) flag = flag & (a[i] == i);
if(flag) {
puts("1.00000000");
continue;
}
for(int i = n;i >= 1;i--) {
if(a[i] != i) {
st = i;
break;
}
}
double ans = 1;
for(int i = 1;i <= m;i++) {
if(r[i] < st) continue;
if(ans == 0) ans = 1-p[i];
else ans = ans * (1-p[i]);
}
printf("%.10lf\n",1-ans);
}
return 0;
}