Luogu p3437 [poi2006] tet Tetris 3D (two-dimensional line tree marking permanent)

Posted by naveenbj on Sat, 07 Dec 2019 19:02:54 +0100

meaning of the title

Title Link

Sol

What is the space complexity of two-dimensional line tree

Why is the whole network space \ (n^2 \) and someone insisted that it is \ (nlog^2n \)

For this problem, because there are modification operations, we need to mark the outer line tree, and the form of the mark is to assign a value to an interval. So we need to open the segment tree for each tag to maintain the changed position

In addition, as we pull down from a line tree, we find the maximum value of the line tree of the subtree and upload it. Obviously, the complexity will explode, so we should consider the permanence of the mark

Specifically, when we write a line segment tree, if we mark an assignment mark on an interval, obviously its subtrees will be affected. And the maximum value of an interval will have an impact on its father, so directly open two arrays to record

And then, in the process of recursion, just deal with the tag

// luogu-judger-enable-o2
// luogu-judger-enable-o2
// luogu-judger-enable-o2
/*

*/ 
#include<bits/stdc++.h>
#define LL long long 
using namespace std;
const int MAXN = 2001, INF = 1e9 + 10;
void chmin(int &a, int b) {a = (a < b ? a : b);}
void chmax(int &a, int b) {a = (a > b ? a : b);}
int sqr(int x) {return x * x;}
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int N, M, Q;
struct InSeg {
    int rt[MAXN], ls[MAXN], rs[MAXN], mx[MAXN], tag[MAXN], tot;
    void update(int k) {
        mx[k] = max(mx[ls[k]], mx[rs[k]]);
    }
    void ps(int k, int v) {
        chmax(mx[k], v);
        chmax(tag[k], v);
    }
    void pushdown(int k) {
        if(!tag[k]) return ;
        if(!ls[k]) ls[k] = ++tot;
        if(!rs[k]) rs[k] = ++tot;
        ps(ls[k], tag[k]); ps(rs[k], tag[k]);
        tag[k] = 0;
    }
    void IntMem(int &k, int l, int r, int ll, int rr, int v) {
        if(!k) k = ++tot;
        if(ll <= l && r <= rr) {ps(k, v); return ;}
        pushdown(k);
        int mid = l + r >> 1;
        if(ll <= mid) IntMem(ls[k], l, mid, ll, rr, v);
        if(rr  > mid) IntMem(rs[k], mid + 1, r, ll, rr, v);
        update(k);
    }
    int Query(int k, int l, int r, int ll, int rr) {
        if(!k) return 0;
        if(ll <= l && r <= rr) return mx[k];
        pushdown(k);
        int mid = l + r >> 1, ans = 0;
        if(ll <= mid) chmax(ans, Query(ls[k], l, mid, ll, rr));
        if(rr  > mid) chmax(ans, Query(rs[k], mid + 1, r, ll, rr));
        return ans;
    }
};
int ls[MAXN], rs[MAXN], rtag[MAXN], rmx[MAXN], tot, root;
InSeg tag[MAXN], mx[MAXN];
void IntMem(int &k, int l, int r, int a, int b, int ll, int rr, int v) {
    if(!k) k = ++tot;
    mx[k].IntMem(rmx[k], 1, M, ll, rr, v);
    if(a <= l && r <= b) {
        tag[k].IntMem(rtag[k], 1, M, ll, rr, v); 
        return ;
    }
    int mid = l + r >> 1;
    if(a <= mid) IntMem(ls[k], l, mid, a, b, ll, rr, v);
    if(b  > mid) IntMem(rs[k], mid + 1, r, a, b, ll, rr, v);
}
int Query(int k, int l, int r, int a, int b, int ll, int rr) {
    if(!k) return 0;
    int ans = tag[k].Query(rtag[k], 1, M, ll, rr);
    if(a <= l && r <= b) return max(ans, mx[k].Query(rmx[k], 1, M, ll, rr));
    int mid = l + r >> 1;
    if(a <= mid) chmax(ans, Query(ls[k], l, mid, a, b, ll, rr));
    if(b  > mid) chmax(ans, Query(rs[k], mid + 1, r, a, b, ll, rr));
    return ans;
}
signed main() {
    N = read(); M = read(); Q = read();
    while(Q--) {
        int d = read(), s = read(), h = read(), x = read(), y = read();
        //printf("**%d %d %d %d %d\n", x + 1, x + d, y + 1, y + s, h);
        IntMem(root, 1, N, x + 1, x + d, y + 1, y + s, Query(root, 1, N, x + 1, x + d, y + 1, y + s)  + h);
    }
    printf("%d\n", Query(1, 1, N, 1, N, 1, M));
    return 0;
}
/*
7 5 4
4 3 2 0 0
3 3 1 3 0
7 1 2 0 3
2 3 3 2 2
*/

Topics: C++ network