Loading

P3657 题解

是不是有点恶意评分了

题目链接

Sol

看完题目就想到了这个题

这道题同样是求线段,不过这个加了点限制,发现一个点最多连 4 条边出去,暴力连边的复杂度是正确的,于是就把这题变成黄了

利用刚刚那道题的 trick,把边按左端点排序后右端点的 LIS 就是答案。

这里给一个更方便的做法,不用真的去连边,直接扫左端点是自动排序好了的,记录每个编号的位置,然后用树状数组 dp 就好。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int N = 1e5 + 5, INF = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
int n;
int a[N], b[N], p[N], f[N];
int c[N];
void modify(int x, int v) {
	for(; x <= n; x += x & -x) c[x] = max(c[x], v);
}
int query(int x) {
	int res = 0;
	for(; x; x -= x & -x) res = max(res, c[x]);
	return res;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
	cin >> n;
	for(int i = 1; i <= n; i ++) {
		cin >> a[i];
	}
	for(int i = 1; i <= n; i ++) {
		cin >> b[i];
		p[b[i]] = i;
	}
	for(int i = 1; i <= n; i ++) {
		queue<int> tmp;
		for(int j = max(1, a[i] - 4); j <= min(n, a[i] + 4); j ++)
			tmp.push(query(p[j] - 1) + 1);
		for(int j = max(1, a[i] - 4); j <= min(n, a[i] + 4); j ++)
			modify(p[j], tmp.front()), tmp.pop();
	}
	cout << query(n) << '\n';
    return 0;
}

注意 dp 的过程中不能刚查询完就改,需要把 i 能找到的所有记录下来最后一起改,不然可能会计算从 i 有两条出边的答案。

posted @   Svemit  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示