CF494C Helping People

http://codeforces.com/problemset/problem/494/C

题解

注意到区间之间没有交叉,所以只有包含的关系,我们可以把它整成一棵树。

然后设一下\(dp[i][j]\)表示以\(i\)为根的子树,最大值不超过区间最大值+\(j\)的概率。

转移:

\[dp[u][j]=p*\prod dp[v][mx[u]-mx[v]-1+j]+(1-p)*\prod dp[v][mx[u]-mx[v]+j] \]

代码

#include<bits/stdc++.h>
#define N 100002
#define M 5002
using namespace std;
typedef long long ll;
int n,nw[N],top,mx[M],q,st[N];
vector<int>vec[N];
double f[M][M],ans,g[M][M];
int size[M];
inline ll rd(){
  ll x=0;char c=getchar();bool f=0;
  while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
  while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
  return f?-x:x;
}
struct node{
  int l,r;double p;
  inline bool operator <(const node &b)const{
    if(l!=b.l)return l<b.l;
    else return r>b.r;   
  }
}a[M];
void dfs(int u){
    int l=a[u].l;
    size[u]=u!=0;
    for(vector<int>::iterator it=vec[u].begin();it!=vec[u].end();++it){
        int v=*it;
        dfs(v);
        for(int i=l;i<a[v].l;++i)mx[u]=max(mx[u],nw[i]);
        mx[u]=max(mx[u],mx[v]);
        l=a[v].r+1;
    }
    for(int i=l;i<=a[u].r;++i)mx[u]=max(mx[u],nw[i]);
    int now=mx[u];
    for(vector<int>::iterator it=vec[u].begin();it!=vec[u].end();++it){
        int v=*it;
        mx[u]=max(mx[u],mx[v]);
    }
    for(int i=0;i<=q;++i){
        f[u][i]=(1-a[u].p);
        g[u][i]=a[u].p;
    } 
    if(now==mx[u])g[u][0]=0;
    for(vector<int>::iterator it=vec[u].begin();it!=vec[u].end();++it){
        int v=*it;
        size[u]+=size[v];
        for(int j=0;j<=size[u];++j){
            if(mx[u]-mx[v]-1+j<=size[u]&&mx[u]-mx[v]-1+j>=0)g[u][j]*=f[v][mx[u]-mx[v]-1+j];
            if(mx[u]-mx[v]+j<=size[u])f[u][j]*=f[v][mx[u]-mx[v]+j];
        }
    }
    for(int i=0;i<=q;++i)f[u][i]+=g[u][i];
}
int main(){
  n=rd();q=rd();
  for(int i=1;i<=n;++i)nw[i]=rd();
  for(int i=1;i<=q;++i){
    a[i].l=rd();a[i].r=rd();scanf("%lf",&a[i].p);
  }
  sort(a+1,a+q+1);
  for(int i=1;i<=q;++i){
    while(top&&a[st[top]].r<a[i].l)top--;
    vec[st[top]].push_back(i);
    st[++top]=i;
  }
  a[0].l=1;a[0].r=n;
  dfs(0);
  for(int i=0;i<=q;++i){
    double x=i?f[0][i]-f[0][i-1]:f[0][0];
    ans+=x*(mx[0]+i);
  }
  printf("%.9lf",ans);
  return 0;
}
posted @ 2019-06-14 20:23  comld  阅读(277)  评论(0编辑  收藏  举报