• Helping People


    由于操作的区间互不重叠,所以我们将区间以相互包含的关系建树

    $n^2$树状dp,设$dp[i][j]$表示第i个区间最大值小于等于$max(a[l[i]],…,a[r[i]])+j$的概率

    设d[i]为$max(a[l[i]],…,a[r[i]])$

    转移还是比较好推的:$dp[i][j]=p_iprodlimits_{v是i的儿子} dp[i][d[i]-d[v]+j-1] space+ space (1-p_i)prodlimits_{v是i的儿子} dp[i][d[i]-d[v]+j]$

    #include<bits/stdc++.h>
    #define maxn 100005
    #define maxm 500005
    #define inf 0x7fffffff
    #define ll long long
    #define rint register int
    #define debug(x) cerr<<#x<<": "<<x<<endl
    #define fgx cerr<<"--------------"<<endl
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define dgx cerr<<"=============="<<endl
    #define lowbit(x) (x&(-x))
    #define MAXN 5005
    using namespace std;
    inline int read(){
    	int x=0,f=1;
    	char ch=getchar();
    	while('0'>ch || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    	while('0'<=ch && ch<='9'){x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();}
    	return x*f;
    }
    int n,m,b[maxn],d[MAXN],book[MAXN];
    double ans,dp[MAXN][MAXN];
    struct node{
    	int l,r;
    	double x;
    }a[MAXN];
    bool cmpp(node a1,node a2){
    	return a1.r-a1.l<a2.r-a2.l;
    }
    struct Segment_Tree{
    	int c[maxn<<2];
    	void build(int k,int l,int r){
    		if(l==r){c[k]=b[l]; return;}
    		int mid=(l+r)>>1;
    		build(k<<1,l,mid); build((k<<1)|1,mid+1,r);
    		c[k]=max(c[k<<1],c[k<<1|1]);
    	}
    	int query(int k,int l,int r,int x,int y){
    		if(x<=l && r<=y) return c[k];
    		int maxx=-1,mid=(l+r)>>1;
    		if(mid>=x) maxx=query(k<<1,l,mid,x,y);
    		if(mid<y) maxx=max(maxx,query((k<<1)|1,mid+1,r,x,y));
    		return maxx;
    	}
    }Q;
    int to[maxn],fir[maxn],nxt[maxn],tot;
    void ade(int x,int y){
    	to[++tot]=y;
    	nxt[tot]=fir[x];
    	fir[x]=tot;
    }
    void work(int x){
    	dp[x][0]=1-a[x].x;
    	d[x]=Q.query(1,1,n,a[x].l,a[x].r);
    	rep(i,1,x-1) if(a[x].l<=a[i].l && a[i].r<=a[x].r && !book[i]){ if(d[x]-d[i]<=m) dp[x][0]*=dp[i][d[x]-d[i]]; ade(x,i);}
    	rep(j,1,m+1){
    		double z1=1,z2=1;
    		for(int i=fir[x];i;i=nxt[i]) if(d[x]-d[to[i]]-1+j<=m) z1=z1*dp[to[i]][d[x]-d[to[i]]-1+j],z2=z2*dp[to[i]][d[x]-d[to[i]]+j];
    		dp[x][j]=z1*a[x].x+z2*(1-a[x].x);
    	}
    	rep(i,1,x-1) if(a[x].l<=a[i].l && a[i].r<=a[x].r && !book[i]) book[i]=1;
    }
    int main(){
        scanf("%d%d",&n,&m);
        rep(i,1,n) b[i]=read();
        rep(i,1,m){
        	a[i].l=read(); a[i].r=read();
        	scanf("%lf",&a[i].x);
    	}
    	m++;Q.build(1,1,n);
    	a[m].l=1; a[m].r=n; a[m].x=0;
    	sort(a+1,a+m+1,cmpp);
    	rep(i,1,m) work(i);ans=d[m]*dp[m][0];
    	rep(i,1,m) ans=ans+(d[m]+i)*(dp[m][i]-dp[m][i-1]);
    	printf("%.10lf",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    对象的访问定位——如何找到对象
    对象的结构
    对象在内存中的布局-对象的创建
    java的内存模型--jmm
    redis 持久化之rdb总结
    简单说springmvc的工作原理
    抽象类和接口的区别
    hashcode和equals的作用区别及联系
    DBC物品中打包物品参数设置
    关于GOM引擎启动时显示:windows socket error: 在其上下文中,该请求的地址无效。 (10049), on API 'bind'
  • 原文地址:https://www.cnblogs.com/handsome-zlk/p/14252341.html
Copyright © 2020-2023  润新知