【10-24模拟赛T1】Alice 和璀璨花

著名的植物学家 Alice 经过多年的探索,终于找到了传说中的璀璨花。璀璨花的生长速度非常迅猛,如果不加以合适的控制,璀璨花会因为过度内耗而死亡。璀璨花的生长趋势可以用序列 \(a\) 表示,Alice 在研读前人对璀璨花的研究后总结出了一个控制序列 \(b\)。Alice 需要让璀璨花的生长趋势尽可能贴合控制序列,这样璀璨花就能尽可能快且安全地生长,以让更多人能欣赏到传说花卉的美。

Alice 可以通过基因编辑技术让 \(a\) 的任意子序列 \(a'\) 成为璀璨花的生长趋势,设 \(a'\) 的长度为 \(n'\),若 \(\forall i \in [1,n' - 1],a'_{i + 1} > b_i a'_i\),那么璀璨花的培育趋势就是安全的。另外,越长的生长趋势能让成熟的璀璨花更美,所以 Alice 想知道可能的最长的璀璨花生长趋势子序列的长度。

\(dp_{i,j}\) 表示前 \(i\) 个数中选 \(j\) 个数的最小结尾,可以得出转移方程:

  • \(a_i > dp_{i - 1,j - 1} b_{j - 1}\),那么 \(dp_{i,j} = \min(a_i,dp_{i - 1,j})\)

  • \(a_i \leq dp_{i - 1,j - 1} b_{j - 1}\),那么 \(dp_{i,j} = dp_{i - 1,j}\)

显然可以用滚动数组压掉一维。

但转移还是 \(O(n ^ 2)\) 的,考虑到 \(dp_{i - 1}\) 是单调不减的,我们 lower_bound 一个位置 \(p\),满足 \(dp_{i - 1,p - 1} < a_i\)\(dp_{i - 1,p} \geq a_i\)
,发现 \(\forall j \in[1,p],dp_{i,j} = dp_{i - 1,j}\)(因为 \(dp_{i - 1,j} < a_i\)),\(\forall j \in[p + 1,n],dp_{i,j} = dp_{i - 1,j}\)(因为 \(dp_{i,j - 1}\) 已经大于 \(a_i\) 了,那么 \(dp_{i,j - 1} b_{j - 1}\) 肯定大于 \(a_i\))。

最后总复杂度 \(O(n \log n)\)

//不开 long long 见祖宗
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 9,INF = 0x7f7f7f7f7f7f7f7f;
int n;
int a[N],b[N];
int dp[N];
signed main(){
	//freopen("alice.in","r",stdin);
	//freopen("alice.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> n;
	for(int i = 1;i <= n;i++)
		cin >> a[i];
	for(int i = 1;i <= n;i++)
		cin >> b[i];
	memset(dp,0x7f,sizeof dp);
	dp[0] = 0;
	for(int i = 1;i <= n;i++){
		int pos = lower_bound(dp + 1,dp + n + 1,a[i]) - dp;
		if(a[i] > dp[pos - 1] * b[pos - 1])
			dp[pos] = min(dp[pos],a[i]);
	}
	for(int ans = n;ans >= 1;ans--)
		if(dp[ans] != INF){
			cout << ans;
			break;
		}
	return 0;
}
posted @ 2024-10-24 13:34  5t0_0r2  阅读(9)  评论(0编辑  收藏  举报