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;
}
posted @ 2024-07-25 21:36  adam01  阅读(30)  评论(0)    收藏  举报