模糊序列 / Hitchhiking in the Baltic States
题目大意
给你一个序列,然后每个位置有可以选的数的范围。
然后要你找到对于所有可能的序列它严格上升子序列的最大长度。
思路
很明显的 DP。
考虑列方程,发现数的范围很大,考虑从答案序列长度下手,设 fi,j 为前 i 个数答案串为 j 长度的最后一个最小是多少。
那么我们显然可以得出这个东西是严格递增的。
那我们考虑新一个数放进来会怎么样。
前面比 l 小的一段全部都会可以放一个 l,这个后面中比 r 小的一段全部都可以放比它大 1 的数。
然后前面那一段由于是递增只有最后一个会有效,所以我们可以相当于这样:
那这一段后面放一个 l,然后把中间的一段全部加一,然后把中间后面的一个删掉。
不难想到可以用 fhq-Treap 加速实现。
代码
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int n, l, r;
struct fhq_Treap {
int ls[1000001], rs[1000001], yj[1000001];
int val[1000001], tot, sz[1000001], root;
int lyza[1000001];
int make_new(int va) {
int now = ++tot;
ls[now] = rs[now] = 0; yj[now] = rand();
val[now] = va; sz[now] = 1; return now;
}
void up(int now) {
sz[now] = sz[ls[now]] + sz[rs[now]] + 1;
}
void downa(int x, int va) {
val[x] += va; lyza[x] += va;
}
void down(int now) {
if (lyza[now]) {
if (ls[now]) downa(ls[now], lyza[now]);
if (rs[now]) downa(rs[now], lyza[now]);
lyza[now] = 0;
}
}
pair <int, int> split_rnk(int now, int rnk) {
if (!now) return make_pair(0, 0);
if (!rnk) return make_pair(0, now);
pair <int, int> re;
down(now);
if (sz[ls[now]] >= rnk) {
re = split_rnk(ls[now], rnk);
ls[now] = re.second; up(now);
re.second = now;
}
else {
re = split_rnk(rs[now], rnk - sz[ls[now]] - 1);
rs[now] = re.first; up(now);
re.first = now;
}
return re;
}
pair <int, int> split_val(int now, int va) {
if (!now) return make_pair(0, 0);
pair <int, int> re;
down(now);
if (va < val[now]) {
re = split_val(ls[now], va);
ls[now] = re.second; up(now);
re.second = now;
}
else {
re = split_val(rs[now], va);
rs[now] = re.first; up(now);
re.first = now;
}
return re;
}
int merge(int x, int y) {
if (!x || !y) return x + y;
if (x) down(x); if (y) down(y);
if (yj[x] < yj[y]) {
rs[x] = merge(rs[x], y);
up(x); return x;
}
else {
ls[y] = merge(x, ls[y]);
up(y); return y;
}
}
void insert(int x, int rnk) {
int now = make_new(x);
pair <int, int> y = split_rnk(root, rnk);
root = merge(merge(y.first, now), y.second);
}
void build(int l, int r) {
for (int i = l; i <= r; i++)
insert((i == 0) ? 0 : 2e9, i);
}
void work(int l, int r) {
pair <int, int> x = split_val(root, l - 1);
pair <int, int> y = split_val(x.second, r - 1);
downa(y.first, 1);
pair <int, int> z = split_rnk(y.second, 1);
y.second = z.second; int tmp = z.first;
down(tmp); val[tmp] = l;
root = merge(x.first, merge(tmp, merge(y.first, y.second)));
}
}T;
int main() {
srand(19491001);
scanf("%d", &n);
T.build(0, n);
for (int i = 1; i <= n; i++) {
scanf("%d %d", &l, &r);
T.work(l, r);
}
printf("%d", T.sz[T.split_val(T.root, 2e9 - 1).first] - 1);
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现