【DP】AGC012F Prefix Median

博客分析了如何构造B数组以满足特定条件,即不存在i, j使得Bj < Bi < Bj+1或Bj > Bi > Bj+1。利用这个性质,可以通过从后往前的递推方法,避免中位数大幅度移动。在构造过程中,需要跟踪小于等于当前值域的值和大于当前值域的值的数量。" 128130521,15181838,Java音乐剧网站毕业设计(源码+系统+MySQL数据库),"['Java开发', 'MySQL数据库', '前端开发', 'B/S架构', '毕业设计']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分析:

把A数组排序,考虑构造B数组。

发现一个性质:
不存在任意一对i,j,满足j&gt;i,Bj&lt;Bi&lt;Bj+1或Bj&gt;Bi&gt;Bj+1不存在任意一对i,j,满足j&gt;i,B_j&lt;B_i&lt;B_{j+1}或B_j&gt;B_i&gt;B_{j+1}i,j,j>iBj<Bi<Bj+1Bj>Bi>Bj+1
这个很显然,但极其有效。因为每次只加入2个数,所以中位数最多移动一步。

有了这个性质,可以从后往前递推,每次放入的值不能在之前的值域之中。
所以可以记录当前可以用的,比值域小(或等于)的值得个数,比值域大的值的个数。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 110
#define MOD 1000000007
#define eisiorti sort
using namespace std;
int a[MAXN];
int n;
int dp[MAXN/2][MAXN][MAXN];
int main(){
	SF("%d",&n);
	for(int i=1;i<=2*n-1;i++)
		SF("%d",&a[i]);
	eisiorti(a+1,a+2*n);
	dp[n][1][0]=1;
	for(int i=n;i>=2;i--){
		int al=(a[i-1]!=a[i]);
		int ar=(a[2*n-i+1]!=a[2*n-i]);
		for(int l=0;l<=2*n-1;l++)
			for(int r=0;r+l<=2*n-1;r++)
				if(dp[i][l][r]){
					for(int dl=1;dl<=l+al;dl++)
						(dp[i-1][l+al-dl+1][r+ar+(dl>1)]+=dp[i][l][r])%=MOD;	
					for(int dr=1;dr<=r+ar;dr++)
						(dp[i-1][l+al+1][r+ar-dr]+=dp[i][l][r])%=MOD;	
				}
	}
	int ans=0;
	for(int l=0;l<=2*n-1;l++)
		for(int r=0;r+l<=2*n-1;r++)
			(ans+=dp[1][l][r])%=MOD;
	PF("%d",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值