[BZOJ1513][POI2006]Tet-Tetris 3D
Posted xjr_01
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ1513][POI2006]Tet-Tetris 3D相关的知识,希望对你有一定的参考价值。
[BZOJ1513][POI2006]Tet-Tetris 3D
试题描述
输入
输出
输入示例
7 5 4 4 3 2 0 0 3 3 1 3 0 7 1 2 0 3 2 3 3 2 2
输出示例
6
数据规模及约定
见“输入”
题解
二维线段树,其实可以理解成线段树套线段树。
外层线段树维护 x 坐标,内层维护 y 坐标;对于一个外层线段树节点 [l, r],它套着一个内层线段树,表示 x 坐标在 [l, r] 范围,y 坐标在 [1, S] 内的部分。所以当修改的时候(这里把子矩形用两个区间描述:[xl, xr] 和 [yl, yr] 分别表示 x 坐标的范围和 y 坐标的范围),在外层线段树找到 [xl, xr] 对应的 log 个区间,然后对于每个经过的区间都需要在它对应的内层线段树中做一个区间 [yl, yr] 取 max 的操作。外层的线段树因为套了另一个线段树所以得打静态标记,就是我们再开一个专门存标记的线段树,当询问的时候如果经过该节点则把该节点对应的存标记的线段树询问一下取个 max,然后再综合那 log 个区间对应的线段树的答案。
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <stack> #include <vector> #include <queue> #include <cstring> #include <string> #include <map> #include <set> using namespace std; const int BufferSize = 1 << 16; char buffer[BufferSize], *Head, *Tail; inline char Getchar() { if(Head == Tail) { int l = fread(buffer, 1, BufferSize, stdin); Tail = (Head = buffer) + l; } return *Head++; } int read() { int x = 0, f = 1; char c = Getchar(); while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = Getchar(); } while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = Getchar(); } return x * f; } #define maxn 1010 #define maxnode 4000010 int ToT, maxv[maxnode], setv[maxnode], lc[maxnode], rc[maxnode]; void pushdown(int o, int l, int r) { if(!setv[o] || l == r){ setv[o] = 0; return ; } if(!lc[o]) lc[o] = ++ToT; setv[lc[o]] = max(setv[lc[o]], setv[o]); maxv[lc[o]] = max(maxv[lc[o]], setv[lc[o]]); if(!rc[o]) rc[o] = ++ToT; setv[rc[o]] = max(setv[rc[o]], setv[o]); maxv[rc[o]] = max(maxv[rc[o]], setv[rc[o]]); setv[o] = 0; return ; } void update(int& o, int l, int r, int ql, int qr, int val) { if(!o) o = ++ToT; pushdown(o, l, r); if(ql <= l && r <= qr) { setv[o] = max(setv[o], val); maxv[o] = max(maxv[o], setv[o]); return ; } int mid = l + r >> 1; if(ql <= mid) update(lc[o], l, mid, ql, qr, val); if(qr > mid) update(rc[o], mid + 1, r, ql, qr, val); maxv[o] = max(maxv[lc[o]], maxv[rc[o]]); return ; } int query(int o, int l, int r, int ql, int qr) { if(!o) return 0; pushdown(o, l, r); if(ql <= l && r <= qr) return maxv[o]; int mid = l + r >> 1, ans = 0; if(ql <= mid) ans = max(ans, query(lc[o], l, mid, ql, qr)); if(qr > mid) ans = max(ans, query(rc[o], mid + 1, r, ql, qr)); return ans; } int rt[maxn<<2], tag[maxn<<2], D, S; void modify(int o, int l, int r, int xl, int xr, int yl, int yr, int val) { update(rt[o], 1, S, yl, yr, val); if(xl <= l && r <= xr) return update(tag[o], 1, S, yl, yr, val); int mid = l + r >> 1, ls = o << 1, rs = ls | 1; if(xl <= mid) modify(ls, l, mid, xl, xr, yl, yr, val); if(xr > mid) modify(rs, mid + 1, r, xl, xr, yl, yr, val); return ; } int ask(int o, int l, int r, int xl, int xr, int yl, int yr) { int ans = query(tag[o], 1, S, yl, yr); if(xl <= l && r <= xr) return max(ans, query(rt[o], 1, S, yl, yr)); int mid = l + r >> 1, ls = o << 1, rs = ls | 1; if(xl <= mid) ans = max(ans, ask(ls, l, mid, xl, xr, yl, yr)); if(xr > mid) ans = max(ans, ask(rs, mid + 1, r, xl, xr, yl, yr)); return ans; } int main() { D = read(); S = read(); int N = read(); while(N--) { int d = read(), s = read(), w = read(), x = read(), y = read(); int tmp = ask(1, 1, D, x + 1, x + d, y + 1, y + s); // printf("%d %d %d %d: %d\n", x + 1, x + d, y + 1, y + s, tmp); modify(1, 1, D, x + 1, x + d, y + 1, y + s, tmp + w); // printf("%d %d\n", tmp + w, ask(1, 1, D, 1, D, 1, S)); } printf("%d\n", ask(1, 1, D, 1, D, 1, S)); return 0; }
当然,我尝试过 kd 树。。。
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <stack> #include <vector> #include <queue> #include <cstring> #include <string> #include <map> #include <set> using namespace std; const int BufferSize = 1 << 16; char buffer[BufferSize], *Head, *Tail; inline char Getchar() { if(Head == Tail) { int l = fread(buffer, 1, BufferSize, stdin); Tail = (Head = buffer) + l; } return *Head++; } int read() { int x = 0, f = 1; char c = Getchar(); while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = Getchar(); } while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = Getchar(); } return x * f; } #define maxn 1000010 #define oo 2000 bool Cur; struct Node { int x[2], mx[2], mn[2], setv, mxv, v; Node() { mx[0] = mx[1] = -oo; mn[0] = mn[1] = oo; setv = mxv = v = 0; } Node(int _x, int _y) { x[0] = _x; x[1] = _y; mx[0] = mx[1] = -oo; mn[0] = mn[1] = oo; setv = mxv = v = 0; } bool operator < (const Node& t) const { return x[Cur] != t.x[Cur] ? x[Cur] < t.x[Cur] : x[Cur^1] < t.x[Cur^1]; } } ns[maxn]; int ToT, lc[maxn], rc[maxn]; #define upd(t) ns[o].mn[t] = min(ns[o].x[t], min(ns[lc[o]].mn[t], ns[rc[o]].mn[t])), ns[o].mx[t] = max(ns[o].x[t], max(ns[lc[o]].mx[t], ns[rc[o]].mx[t])) void maintain(int o) { if(!o) return ; ns[0] = Node(); upd(0); upd(1); if(!ns[o].setv) ns[o].mxv = max(ns[o].v, max(ns[lc[o]].mxv, ns[rc[o]].mxv)); else ns[o].mxv = ns[o].v = ns[o].setv; return ; } void build(int& o, int l, int r, bool cur) { if(l > r){ o = 0; return ; } int mid = l + r >> 1; o = mid; Cur = cur; nth_element(ns + l, ns + mid, ns + r + 1); build(lc[o], l, mid - 1, cur ^ 1); build(rc[o], mid + 1, r, cur ^ 1); return maintain(o); } void pushdown(int o) { if(!ns[o].setv) return ; ns[lc[o]].setv = ns[lc[o]].mxv = ns[lc[o]].v = ns[rc[o]].setv = ns[rc[o]].mxv = ns[rc[o]].v = ns[o].setv; ns[0] = Node(); ns[o].setv = 0; return ; } Node cmd; #define all(t, o) (cmd.mn[t] <= ns[o].mn[t] && ns[o].mx[t] <= cmd.mx[t]) #define alln(t, o) (ns[o].mx[t] < cmd.mn[t] || cmd.mx[t] < ns[o].mn[t]) #define in(t, o) (cmd.mn[t] <= ns[o].x[t] && ns[o].x[t] <= cmd.mx[t]) void update(int o, int val) { if(!o) return ; pushdown(o); if(in(0, o) && in(1, o)) ns[o].v = val; if(all(0, lc[o]) && all(1, lc[o])) ns[lc[o]].setv = ns[lc[o]].mxv = ns[lc[o]].v = val; else if(!alln(0, lc[o]) && !alln(1, lc[o])) update(lc[o], val); if(all(0, rc[o]) && all(1, rc[o])) ns[rc[o]].setv = ns[rc[o]].mxv = ns[rc[o]].v = val; else if(!alln(0, rc[o]) && !alln(1, rc[o])) update(rc[o], val); return maintain(o); } int query(int o) { if(!o) return 0; pushdown(o); int ans = (in(0, o) && in(1, o)) ? ns[o].v : 0; if(all(0, lc[o]) && all(1, lc[o])) ans = max(ans, ns[lc[o]].mxv); else if(!alln(0, lc[o]) && !alln(1, lc[o])) ans = max(ans, query(lc[o])); if(all(0, rc[o]) && all(1, rc[o])) ans = max(ans, ns[rc[o]].mxv); else if(!alln(0, rc[o]) && !alln(1, rc[o])) ans = max(ans, query(rc[o])); return ans; } int main() { // freopen("data.in", "r", stdin); // freopen("data.out", "w", stdout); int D = read(), S = read(), N = read(); for(int i = 1; i <= D; i++) for(int j = 1; j <= S; j++) ns[++ToT] = Node(i, j); int rt, tot; build(rt, 1, ToT, 0); while(N--) { int d = read(), s = read(), w = read(), x = read(), y = read(); cmd.mn[0] = x + 1; cmd.mn[1] = y + 1; cmd.mx[0] = x + d; cmd.mx[1] = y + s; int tmp = query(rt); // printf("(%d, %d) (%d, %d) %d %d\n", cmd.mn[0], cmd.mn[1], cmd.mx[0], cmd.mx[1], tmp, tmp + w); update(rt, tmp + w); } cmd.mn[0] = cmd.mn[1] = 1; cmd.mx[0] = D; cmd.mx[1] = S; printf("%d\n", query(rt)); return 0; }
敢不敢交由你。。。
以上是关于[BZOJ1513][POI2006]Tet-Tetris 3D的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ1513[POI2006]Tet-Tetris 3D 二维线段树
BZOJ 1513: [POI2006]Tet-Tetris 3D
BZOJ1513[POI2006]Tet-Tetris 3D
BZOJ1513 [POI2006]Tet-Tetris 3D 二维线段树