zoukankan      html  css  js  c++  java
  • codeforces494C Helping People【treedp+概率dp】

    区间不交叉,可以看出区间构成了树形结构,建出树之后,设f[u][i]为u这个区间最大值最多加i的概率,转移是( f[u][i]=p[u]*prod f[v][mxu-mxv-1]+(1-p[u])*prod f[v][mxu-mxv] )
    注意要理性选择建树方式,扫描就行了,不要瞎二分调一年……

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int N=500005;
    int n,m,a[N+1],st[N][20],b[N],mx;
    double f[5005][5005];
    bool vis[N+1];
    vector<int>v[N<<1];
    struct qwe
    {
    	int l,r;
    	double p;
    }q[N<<1];
    bool cmp(qwe a,qwe b)
    {
    	return a.l<b.l||(a.l==b.l&&a.r>b.r);
    }
    int read()
    {
        int r=0,f=1;
        char p=getchar();
        while(p>'9'||p<'0')
        {
            if(p=='-')
                f=-1;
            p=getchar();
        }
        while(p>='0'&&p<='9')
        {
            r=r*10+p-48;
            p=getchar();
        }
        return r*f;
    }
    int build(int u,int fa,int ql,int qr,int w)
    {
    	if(u) 
    		v[fa].push_back(u);
    	vis[u]=1;
    	int x=-1;
    	for(int l=w,r;l<=m;l=r)
    	{
    		if(qr<q[l].r)
    		{
    			x=l;
    			break;
    		}
    		r=build(l,u,q[l].l,q[l].r,l+1);
    	}
    	return x==-1?m+1:x;
    }
    int ques(int l,int r)
    {
    	if(l>r) 
    		return 0;
    	int x=b[r-l+1];
    	return max(st[l][x],st[r-(1<<x)+1][x]);
    }
    void dfs(int u,int fa)
    {
    	if(v[u].empty())
    	{
    		f[u][0]=1.0-q[u].p;
    		for(int i=1;i<=m*2;i++) 
    			f[u][i]=1.0;
    		return;
    	}
    	int w=ques(q[u].l,q[u].r);
    	for(int i=0;i<v[u].size();i++) 
    		dfs(v[u][i],u);
    	for(int i=0;i<=m;i++)
    	{
    		double x=1,y=1;
    		for(int j=0;j<v[u].size();j++)
    			x*=f[v[u][j]][min(m+1,w+i-1-ques(q[v[u][j]].l,q[v[u][j]].r))],y*=f[v[u][j]][min(m+1,w+i-ques(q[v[u][j]].l,q[v[u][j]].r))];
    		f[u][i]=(i?q[u].p:0)*x+(1.0-q[u].p)*y;
    	}
    	f[u][m+1]=1;
    	return ;
    }
    int main()
    {
    	n=read(),m=read();
    	for(int i=1;i<=n;i++) 
    		st[i][0]=a[i]=read(),mx=max(mx,a[i]);
    	if(mx>m) 
    		for(int i=1;i<=n;i++) 
    			st[i][0]=a[i]=max(0,a[i]+m-mx);
    	for(int i=2;i<=n;i++) 
    		b[i]=b[i>>1]+1;
    	for(int j=1;j<=18;j++) 
    		for(int i=1;i+(1<<j)-1<=n;i++) 
    			st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
    	for(int i=1;i<=m;i++) 
    		q[i].l=read(),q[i].r=read(),scanf("%lf",&q[i].p);
    	sort(q+1,q+m+1,cmp);
    	q[0].l=1,q[0].r=n,q[0].p=0;
    	build(0,-1,1,n,1);
    	dfs(0,-1);
    	double ans=mx;
    	for(int i=1;i<=m;i++) 
    		ans+=(f[0][i]-f[0][i-1])*i;
    	printf("%.8lf
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    在SQLite中使用索引优化查询速度
    SQLite支持的SQL数据操作
    left (outer) join , right (outer) join, full (outer) join, (inner) join, cross join 区别
    深入理解Android内存管理原理(六)
    Merge Sorted Array
    Sort Colors
    Construct Binary Tree from Preorder and Inorder Traversal
    Binary Tree Postorder Traversal
    Symmetric Tree
    Rotate Image
  • 原文地址:https://www.cnblogs.com/lokiii/p/11032216.html
Copyright © 2011-2022 走看看