【题解】I love random (计数 dp)

题意

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

sol:

考点:思维 + 计数 dp 。(考验选手的 dp 和模型转化能力)

为了解决这道题,我们引入 极大作用区间 这个概念。即对于每个 P [ i ] P[i] P[i] 找到极大的区间 [ l i , r i ] [l_i,r_i] [li,ri] ,使得 P [ i ] P[i] P[i] 是这个区间的最小值。这样对于 [ l , r ] [l,r] [l,r] 以内的任意子区间都可被染成 P [ i ] P[i] P[i],反之则不能。

现在我们将原问题转化为:对每个 P [ i ] P[i] P[i] 控制的区间 [ l i , r i ] [l_i,r_i] [li,ri] 选出一段子区间去 覆盖完 [1,n] ,问你覆盖的方案数。同时因为对于相同的 P[i] 的控制区间是 绝不相交 的,所以不会算重。

d p [ i ] [ j ] dp[i][j] dp[i][j] 表示处理了 P [ 1.. i ] P[1..i] P[1..i] 同时覆盖了 [ 1 , j ] [1,j] [1,j] 的方案数

进一步深挖性质可以得到按 P[1…n] 的 dp 顺序 (这也是难点,不过需要简单证明,可以证明是不会出现交叉染色的情况的,因为 min 有严格递减的性质)

考虑怎么从 i-1 推到 i :

dp[i][j] = dp[i-1][j] (P[i] 为空的情况)

l[i] <= j <= r[i]

dp[i][j] = ∑l[i]-1<=j’<=j-1 dp[i-1][j’]

时间复杂度 o(n^2) 。

#include <bits/stdc++.h> #define db double #define ll long long #define eps 1e-15 using namespace std; const int N=5005; const int mod=1e9+7; int n,a[N],l[N],r[N]; int s[N],cnt; int dp[2][N],sum; void add(int &x,int y) { x=(x+y)%mod; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } for(int i=1;i<=n;i++) { while(cnt&&a[s[cnt]]>a[i]) cnt--; l[i]=s[cnt]+1; s[++cnt]=i; } s[0]=n+1; cnt=0; for(int i=n;i>=1;i--) { while(cnt&&a[s[cnt]]>a[i]) cnt--; r[i]=s[cnt]-1; s[++cnt]=i; } for(int i=0;i<=r[1];i++) dp[1][i]=1; for(int i=2;i<=n;i++) { int sum=0; for(int j=0;j<=n;j++) { add(dp[i&1][j],dp[i-1&1][j]); if(l[i]<=j&&j<=r[i]) add(dp[i&1][j],sum); if(l[i]-1<=j&&j<=r[i]) add(sum,dp[i-1&1][j]); dp[i-1&1][j]=0; } } printf("%lld",dp[n&1][n]); }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530216.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(7)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示