CF56E 题解
考虑骨牌 \(i\) 倒下之后会比上一块多压倒哪些骨牌。
一种是压不到上一块,答案为 1。
否则答案一定是上一块的答案加上 上一块没有压倒的一些骨牌。
注意到骨牌倒下的影响可以分成许多段,段内骨牌倒下会一直影响到段尾,但不会跨过该段。
这可以用栈维护骨牌互不影响的段的左端点。
具体地,加入新骨牌的时候判断是否会压到前一个段的左端点,压到就更新答案,把答案加上段长,然后弹栈。
最后把当前位置加入栈,标志有新的段。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
struct node{int pos, h, id;} a[N];
int pos[N], ans[N], id[N];
int s[N], h;
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);
int n; cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i].pos >> a[i].h, a[i].id = i;
sort(a + 1, a + n + 1, [](auto &x, auto &y) {return x.pos < y.pos;});
for(int i = 1; i <= n; i ++) id[a[i].id] = i;
for(int i = 1; i <= n; i ++) pos[i] = a[i].pos;
ans[n] = 1;
s[++h] = n;
for(int i = n - 1; i >= 1; i --)
{
ans[i] = 1;
while(h && pos[s[h]] - pos[i] < a[i].h) ans[i] = max(ans[i], ans[s[h]] + s[h] - i), h --;
s[++h] = i;
}
for(int i = 1; i <= n; i ++) cout << ans[id[i]] << " ";
return 0;
}