W
e
l
c
o
m
e
: )

题解:SP1741 TETRIS3D - Tetris 3D

题意

维护一个 \(D\times S\) 的平面,每个点有一个高度。

要求支持一个操作:查询一个矩形区域的最大值,并将该区域更新为最大值加上给定的数。

分析

发现 \(D,S\leq10^3\),考虑使用二维线段树维护。

二维线段树,顾名思义,就是在普通线段树的每一个节点上维护一棵线段树。

在本题中,外层节点上的最大值 mx 和懒标记 tag 均为一棵普通线段树。

普通的修改和查询操作和一般线段树无异。

但是普通的标记下放会涉及到线段树合并,单次下放有可能卡到 \(O(D\log D)\)

所以本题需要使用标记永久化的技巧。

具体地说,标记不会下放,而是在查询的时候连带标记一同查询。

时间复杂度 \(O(N\log^2D)\)

Code

#include<bits/stdc++.h>
using namespace std;
#define maxv 1000

#define mid ((l+r)>>1)
#define lson x->lc, l, mid
#define rson x->rc, mid+1, r

struct In_SegT
{
    struct node
    {
        node *lc, *rc;
        int mx, tag;
        node() {lc=rc=0, mx=tag=0;}
    }*rt;

    In_SegT() {rt=0;}

    void modify(node *&x, int l, int r, int L, int R, int v)
    {
        if(!x) x=new node;
        x->mx=max(x->mx, v);
        if(L<=l&&r<=R) return x->tag=max(x->tag, v), void();
        if(L<=mid) modify(lson, L, R, v);
        if(R>mid)  modify(rson, L, R, v);
    }

    int query(node *x, int l, int r, int L, int R)
    {
        if(!x) return 0;
        if(L<=l&&r<=R) return x->mx;
        int ret=x->tag;
        if(L<=mid) ret=max(ret, query(lson, L, R));
        if(R>mid)  ret=max(ret, query(rson, L, R));
        return ret;
    }

    void modify(int L, int R, int v) {modify(rt, 1, maxv, L, R, v);}
    int query(int L, int R)          {return query(rt, 1, maxv, L, R);}
};

struct Out_SegT
{
    struct node
    {
        node *lc, *rc;
        In_SegT *mx, *tag;
        node() {lc=rc=0, mx=new In_SegT, tag=new In_SegT;}
    }*rt;

    void modify(node *&x, int l, int r, int L1, int R1, int L2, int R2, int v)
    {
        if(!x) x=new node;
        x->mx->modify(L2, R2, v);
        if(L1<=l&&r<=R1) return x->tag->modify(L2, R2, v);
        if(L1<=mid) modify(lson, L1, R1, L2, R2, v);
        if(R1>mid)  modify(rson, L1, R1, L2, R2, v);
    }

    int query(node *x, int l, int r, int L1, int R1, int L2, int R2)
    {
        if(!x) return 0;
        if(L1<=l&&r<=R1) return x->mx->query(L2, R2);
        int ret=x->tag->query(L2, R2);
        if(L1<=mid) ret=max(ret, query(lson, L1, R1, L2, R2));
        if(R1>mid)  ret=max(ret, query(rson, L1, R1, L2, R2));
        return ret;
    }
}tr;

int main()
{
    int d, s, n, w, x, y;
    cin>>d>>s>>n;
    while(n--)
    {
        cin>>d>>s>>w>>x>>y;
        int h0=tr.query(tr.rt, 1, maxv, x+1, d+x, y+1, s+y);
        tr.modify(tr.rt, 1, maxv, x+1, d+x, y+1, s+y, h0+w);
    }
    cout<<tr.rt->mx->rt->mx;
}
posted @ 2024-09-24 16:30  Jimmy-LEEE  阅读(11)  评论(0)    收藏  举报