专栏文章

题解:P14078 [GESP202509 七级] 金币收集

P14078题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minp0kl3
此快照首次捕获于
2025/12/02 06:00
3 个月前
此快照最后确认于
2025/12/02 06:00
3 个月前
查看原文
一种无脑做法。
先给原序列排序,按 xx 为第一关键字 tt 为第二关键字从小到大排序。
然后考虑线性 dp,令 fif_i 表示 [1,i][1,i] 进行完决策且第 ii 个金币选了的最优金币数。有转移:
{xi>ti,fi=0xiti,fi=maxj[1,i),xixjtitjfj+1\begin{cases} x_i>t_i,f_i=0\\ x_i\leq t_i,f_i=\max_{j\in [1,i),x_i-x_j\leq t_i-t_j} f_j+1 \end{cases}
答案是 maxi=1nfi\max_{i=1}^n f_i,直接硬做是 O(n2)O(n^2),只能拿 70pts。
观察合法转移的判定条件:
xixjtitjx_i-x_j\leq t_i-t_j
移项:
xitixjtjx_i-t_i\leq x_j-t_j
这样有关 iijj 的量都移到了一边,这样我们可以先对 xitix_i-t_i 离散化,然后用一个支持单点取 max\max / 区间查 max\max 的线段树优化转移即可,时间复杂度 O(nlogn)O(n\log n),可以通过。
CPP
#include <bits/stdc++.h>
using namespace std;
#define il inline
typedef long long ll;
const int N = 1e5 + 10;
struct node
{
	int x, t;
	friend bool operator < (const node &n1, const node &n2)
	{
		return n1.x == n2.x ? n1.t < n2.t : n1.x < n2.x;
	}
}a[N];
int f[N], n, tot;
unordered_map<int, int> mp;
set<int> s;
struct node2
{
	int v;
}ST[N << 2];
il void push_up(int ind)
{
	ST[ind].v = max(ST[ind << 1].v, ST[ind << 1 | 1].v);
}
il void upd(int ind, int l, int r, int tl, int tr, int x)
{
	if(l == r)
	{
		ST[ind].v = max(ST[ind].v, x);
		return;
	}
	int mid = (l + r) >> 1;
	if(tl <= mid) upd(ind << 1, l, mid, tl, tr, x);
	if(tr > mid) upd(ind << 1 | 1, mid + 1, r, tl, tr, x);
	push_up(ind);
}
il int ask(int ind, int l, int r, int tl, int tr)
{
	if(tl > tr) return 0;
	if(tl <= l && r <= tr) return ST[ind].v;
	int mid = (l + r) >> 1;
	if(tl <= mid && tr > mid) return max(ask(ind << 1, l, mid, tl, tr), ask(ind << 1 | 1, mid + 1, r, tl, tr));
	if(tl <= mid) return ask(ind << 1, l, mid, tl, tr);
	return ask(ind << 1 | 1, mid + 1, r, tl, tr);
}
int main()
{
	cin >> n;
	for(int i = 1;i <= n;++i) 
	{
		cin >> a[i].x >> a[i].t;
		s.insert(a[i].x - a[i].t);
	}
	sort(a + 1, a + 1 + n);
	for(auto i : s) mp[i] = ++tot;
	int ans = 0;
	for(int i = 1;i <= n;++i)
	{
		if(a[i].x > a[i].t) continue;
		f[i] = ask(1, 1, tot, mp[a[i].x - a[i].t], tot) + 1;
		ans = max(ans, f[i]);
		upd(1, 1, tot, mp[a[i].x - a[i].t], mp[a[i].x - a[i].t], f[i]);
	}
	cout << ans;
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...