IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【模拟赛】排队(动态规划) -> 正文阅读

[数据结构与算法]【模拟赛】排队(动态规划)

题面

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

题解

我们令 d ( i ) d(i) d(i) i i i 位置前比 a i a_i ai? 大的数个数,我们想要的就是 ∑ i = 1 n d ( i ) \sum_{i=1}^n d(i) i=1n?d(i)

然而我们只能得到 ∑ i = 1 n max ? ( i ? a i , 0 ) \sum_{i=1}^n \max(i-a_i,0) i=1n?max(i?ai?,0)

但是不难发现 d ( i ) ≥ max ? ( i ? a i , 0 ) d(i)\geq \max(i-a_i,0) d(i)max(i?ai?,0)

所以我们要让两个求和相等,就必须让每个位置的 d ( i ) = max ? ( i ? a i , 0 ) d(i)=\max(i-a_i,0) d(i)=max(i?ai?,0) 。把这个条件翻译一下,就是说,每个数前面要么不存在比它大的数,要么存在所有比它小的数

我们可以考虑从左往右向排列中填数,那么每次只有两种选择,其一是填入比最大值大的一个数,其二是填入 前缀集合 ∪ { 0 } \cup\{0\} {0} m e x \rm mex mex ,可以利用这个方法判断前 M M M 个是否合法。令 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示填了第 i i i 个数,最大值为 j j j 的方案数,那么
d p [ i ] [ j ] = 0 ???? ( j < i ) d p [ i ] [ j ] = d p [ i ? 1 ] [ j ] + ∑ k < j d p [ i ? 1 ] [ k ] dp[i][j]=0~~~~(j<i)\\ dp[i][j]=dp[i-1][j]+\sum_{k<j}dp[i-1][k] dp[i][j]=0????(j<i)dp[i][j]=dp[i?1][j]+k<j?dp[i?1][k]

这样其实不好做,我们令 s u m [ i ] [ j ] = ∑ k = 1 j d p [ i ] [ k ] sum[i][j]=\sum_{k=1}^j dp[i][k] sum[i][j]=k=1j?dp[i][k] ,那么
s u m [ i ] [ j ] = s u m [ i ] [ j ? 1 ] + ( s u m [ i ? 1 ] [ j ] ? s u m [ i ? 1 ] [ j ? 1 ] ) + s u m [ i ? 1 ] [ j ? 1 ] = s u m [ i ] [ j ? 1 ] + s u m [ i ? 1 ] [ j ] sum[i][j]=sum[i][j-1]+(sum[i-1][j]-sum[i-1][j-1])+sum[i-1][j-1]\\ =sum[i][j-1]+sum[i-1][j] sum[i][j]=sum[i][j?1]+(sum[i?1][j]?sum[i?1][j?1])+sum[i?1][j?1]=sum[i][j?1]+sum[i?1][j]

最后这个式子非常美观,以至于很容易想到网格图上行走。
s u m [ x ] [ y ] → { s u m [ x + 1 ] [ y ] s u m [ x ] [ y + 1 ] sum[x][y]\rightarrow \begin{cases} sum[x+1][y]\\ sum[x][y+1] \end{cases} sum[x][y]{sum[x+1][y]sum[x][y+1]?

我们把前 M M M 个判断后,可以得到最大值 m x mx mx ,那么最终的答案就是从 ( M , m x ) (M,mx) (M,mx) 右走或上走走到 ( N , N ) (N,N) (N,N) ,中途不越过 x = y x=y x=y (保持 y ≥ x y\geq x yx)的方案数。用两个组合数就好了:
C ( 2 N ? M ? m x , N ? M ) ? C ( 2 N ? M ? m x , N ? M + 1 ) C(2N-M-mx,N-M)-C(2N-M-mx,N-M+1) C(2N?M?mx,N?M)?C(2N?M?mx,N?M+1)

时间复杂度 O ( 对 1 0 5 的 嘲 讽 ) O(对 10^5 的嘲讽) O(105)

CODE

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<random>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 100005
#define LL long long
#define ULL unsigned long long
#define ENDL putchar('\n')
#define DB double
#define lowbit(x) (-(x) & (x))
#define FI first
#define SE second
int xchar() {
	static const int maxn = 1000000;
	static char b[maxn];
	static int pos = 0,len = 0;
	if(pos == len) pos = 0,len = fread(b,1,maxn,stdin);
	if(pos == len) return -1;
	return b[pos ++];
}
//#define getchar() xchar()
LL read() {
	LL f = 1,x = 0;int s = getchar();
	while(s < '0' || s > '9') {if(s<0)return -1;if(s=='-')f=-f;s = getchar();}
	while(s >= '0' && s <= '9') {x = (x<<1) + (x<<3) + (s^48);s = getchar();}
	return f*x;
}
void putpos(LL x) {if(!x)return ;putpos(x/10);putchar((x%10)^48);}
void putnum(LL x) {
	if(!x) {putchar('0');return ;}
	if(x<0) putchar('-'),x = -x;
	return putpos(x);
}
void AIput(LL x,int c) {putnum(x);putchar(c);}

const int MOD = 1000000007;
int n,m,s,o,k;
int fac[MAXN<<1],inv[MAXN<<1],invf[MAXN<<1];
int C(int n,int m) {
	if(m < 0 || m > n) return 0;
	return fac[n] *1ll* invf[n-m] % MOD * invf[m] % MOD;
}
int a[MAXN];
int c[MAXN];
void addc(int x,int y) {while(x<=n)c[x]+=y,x+=lowbit(x);}
int sum(int x) {int s=0;while(x)s+=c[x],x-=lowbit(x);return s;}
int main() {
	freopen("queue.in","r",stdin);
	freopen("queue.out","w",stdout);
	n = read();m = read();
	fac[0]=fac[1]=inv[0]=inv[1]=invf[0]=invf[1]=1;
	for(int i = 2;i <= n*2;i ++) {
		fac[i] = fac[i-1] *1ll* i % MOD;
		inv[i] = (MOD - inv[MOD%i]) *1ll* (MOD/i) % MOD;
		invf[i] = invf[i-1] *1ll* inv[i] % MOD;
	}
	int mx = 0,flag = 1;
	for(int i = 1;i <= m;i ++) {
		a[i] = read();
		mx = max(mx,a[i]);
		addc(a[i],1);
		if(a[i] != mx) {
			if(sum(a[i]) != a[i]) flag = 0;
		}
	}
	if(!flag) return printf("0\n"),0;
	int rr = n-m,cc = n-mx;
	int ans = (C(rr+cc,rr) +MOD- C(rr+cc,rr+1)) % MOD;
	AIput(ans,'\n');
	return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-28 15:50:37  更:2022-02-28 15:53:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:43:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码