[luoguAT_abc382_f] Falling Bars

题意

W×H 的网格,上面 n1×Li 的方块,最左侧位置为 (Ri,Ci),求这些方块下落后行 Ri 是多少。

sol

可以按照 Ri 对每个方块从大到小排序,容易发现下落时一定要按照方块顺序操作。当下落时,方块在第 Ri 行当且仅当第 Ri 行的对应位置没有方块,且 Ri+1 行的至少一个对应位置有方块(或是边界)。我们发现这个位置是对应列可放位置的最小值。
使用线段树来维护最小值,这样这道题就变成了区改区查最小值的线段树问题。
注意处理好 lazytagtr 之间的关系。

代码

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 200005;

struct Block{
    int r, c, l, id;
    bool operator< (const Block &W) const {
        if (r != W.r) return r > W.r;
        return c < W.c;
    }
} blocks[N];

int h, w, n;
int tr[N << 2], lazytag[N << 2];
int ans[N];

void build(int u, int l, int r){
    if (l == r) {
        tr[u] = h;
        lazytag[u] = h;
        return ;
    }

    int mid = l + r >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    lazytag[u] = tr[u] = h;
}

void pushdown(int u, int l, int r){
    if (l != r){
        lazytag[u << 1] = min(lazytag[u], lazytag[u << 1]);
        tr[u << 1] = min(lazytag[u], tr[u << 1]);
        lazytag[u << 1 | 1] = min(lazytag[u], lazytag[u << 1 | 1]);
        tr[u << 1 | 1] = min(lazytag[u], tr[u << 1 | 1]);
    }
}

void update(int u, int l, int r, int L, int R, int x){
    if (L <= l && r <= R) {
        lazytag[u] = x;
        tr[u] = x;
        return ;
    }
    pushdown(u, l, r);
    int mid = l + r >> 1;
    if (L <= mid) update(u << 1, l, mid, L, R, x);
    if (R > mid) update(u << 1 | 1, mid + 1, r, L, R, x);
    tr[u] = min(tr[u << 1], tr[u << 1 | 1]);
}

int query(int u, int l, int r, int L, int R){
    if (L <= l && r <= R) return tr[u];
    pushdown(u, l, r);
    int mid = l + r >> 1, minn = 0x3f3f3f3f;
    if (L <= mid) minn = min(minn, query(u << 1, l, mid, L, R));
    if (R > mid) minn = min(minn, query(u << 1 | 1, mid + 1, r, L, R));
    return minn;
}

int main(){
    scanf("%d%d%d", &h, &w, &n);
    for (int i = 1; i <= n; i ++ ) scanf("%d%d%d", &blocks[i].r, &blocks[i].c, &blocks[i].l), blocks[i].id = i;

    sort(blocks + 1, blocks + n + 1);

    build(1, 1, w);

    for (int i = 1; i <= n; i ++ ){
        ans[blocks[i].id] = query(1, 1, w, blocks[i].c, blocks[i].c + blocks[i].l - 1);
        update(1, 1, w, blocks[i].c, blocks[i].c + blocks[i].l - 1, ans[blocks[i].id] - 1);
    }

    for (int i = 1; i <= n; i ++ ) printf("%d\n", ans[i]);
}

蒟蒻犯的若至错误

  • 线段树写炸了
posted @   是一只小蒟蒻呀  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示