#797 Div.3 G. Count the Trains 思维

这篇博客讨论了一种车辆速度限制问题,其中需要保持每辆车的速度不超过前车且不超过自身最大限速。文章提出了维护最长严格下降子序列的思路来解决这个问题,并给出了O(nlogn)的时间复杂度的解决方案。代码实现中使用了map数据结构来动态更新序列,并在每次修改后更新序列的段数。
摘要由CSDN通过智能技术生成

1690G
2000,思维,数据结构

题意

n n n 辆车排成一列,每列车的速度不能超过前面的车的速度也不能超过自己的最高限速,现给出它们的最高限速。并给出 m m m 次修改:形如 i,x ,表示将第 i i i 辆车的最高限速降低 x x x ,保证任意时刻车的速度为非负。求出每次操作后序列的总段数是多少。(例如 111,211,321分别算1、2、3段)。

思路

题目意思就是维护一个最长严格下降子序列的长度。
注意到修改只有降低,没有升高。也就是说假如第 i i i 辆车对答案没有贡献,那么之后除非对第 i i i 辆车进行修改,否则它永远对答案没有贡献,同时即便修改了其他值,也不会影响它们是否对答案有贡献,因此我们可以在下次修改 i i i 之前直接忽略它。
这里我们考虑用 map, [i, a[i]] —— i 表示位置 a[i]表示值 维护这个最长不下降子序列,则 size() 便是长度,显然这个序列的 a[i] 满足严格单减。当某个 a [ i ] a[i] a[i] 修改后,我们把 [ i , a [ i ] ] [i,a[i]] [i,a[i]] 加入集合(如果 i i i 已经在集合里,就修改它的映射),这时如果它的前驱比它小,那么它对答案没有贡献,直接从映射中删除。否则删去所有比它大的后继,维护集合的单调性。
这里直接暴力遍历并删除就可以了,因为每次只添加了1个数,所以删除操作最多只会进行 2 n − 1 2n-1 2n1 次,总时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn)

代码

int n, m;
int a[maxn];
map<int, int> s;
void add(int i, int x) {
	s[i] = x;
	auto it = s.find(i);
	if(it != s.begin() && x >= prev(it)->second) {
		s.erase(it);
		return;
	}
	while(next(it) != s.end() && x <= next(it)->second) {
		s.erase(next(it));
	}
}
void solve() {
	cin >> n >> m;
	s.clear();
	for(int i = 1; i <= n; i++) {
		cin >> a[i];
		add(i, a[i]);
	}
	while(m--) {
		int i, x;
		cin >> i >> x;
		a[i] -= x;
		add(i, a[i]);
		cout << s.size() << " \n"[!m];
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值