【动态规划 LIS】JZOJ_6310 glo

本文探讨了在一个序列上进行区间加法操作以最大化最长递增子序列(LIS)的问题。通过分析,发现最优策略是在选定区间的右边界至序列末尾应用加法,且加数绝对值不超过给定限制。文章进一步解释了为什么此策略有效,并提供了一个基于两次遍历序列和使用lower_bound函数的C++实现。

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

题意

给出n和x,还有一个大小为n的序列a。
让你选取一个区间[l,r],让al..ra_{l..r}al..r都加上d(∣d∣≤x)(|d|\leq x)(dx),最大化a的LIS。

思路

如果在[l,r]加上d,不如在[l,n]加上d,并不会使答案更劣。
证:因为在[l,r]加上d,增加的LIS肯定从前面转移过来,[r+1,n]同时加的话,不会使答案更劣。

d≥0d\geq0d0,因为d&lt;0d&lt;0d<0可以转化成d≥0d\geq0d0(减操作相当于在后面做加操作)。
所以d=xd=xd=x,对答案没有影响。

故枚举一个中间点,合并一下到i未加x的LIS和i到加x的LIS。

代码

#include <cstdio>
#include <iostream>
#include <algorithm>
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)

int n, x, cnt, ans;
int a[200001], f[200001], g[200001];

int main() {
	file(glo);
	scanf("%d %d", &n, &x);
	for (int i = 1; i <= n; i++)
		scanf("%d", a + i);
	for (int i = 1, pos; i <= n; i++) {
		g[i] = std::lower_bound(f + 1, f + cnt + 1, a[i] + x) - f - 1;
		pos = std::lower_bound(f + 1, f + cnt + 1, a[i]) - f;
		f[pos] = a[i];
		cnt = std::max(cnt, pos);
	}
	cnt = 0;
	for (int i = n, pos; i >= 1; i--) {
		pos = std::lower_bound(f + 1, f + cnt + 1, a[i], std::greater<int>()) - f;
		f[pos] = a[i];
		cnt = std::max(cnt, pos);
		ans = std::max(ans, g[i] + pos);
	}
	printf("%d", ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值