P5621 [DBOI2019]德丽莎世界第一可爱
P5621 [DBOI2019]德丽莎世界第一可爱 本题最优解
题目传送门
前置知识:带修
用的不是
本题主要讲解的不是带修
我们发现这是一个典型的四维偏序问题,我们一次将一二三四维排序后,就可以
我们先把一个带修
优化
优化
优化
优化
优化
优化
加上这些优化,您就可以享受从
最后,如果对有些优化不清楚,可以参考代码。
#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline T sqr(T x) { return x * x; }
#define lc(x) w[x].l
#define rc(x) w[x].r
const int N = 2e5 + 10;
const double alpha = 0.715;
const int SIZ = 1 << 14;
inline char getc() {
static char bf[SIZ], *begin = bf, *end = bf;
if (begin == end) begin = bf, end = bf + fread(bf, 1, SIZ, stdin);
if (begin == end) return EOF;
return *begin++;
}
inline int read() {
static char tmp;
static int ans, flag;
tmp = getc(), flag = 1, ans = 0;
while (!isdigit(tmp)) {
if (tmp == '-') flag = -1;
tmp = getc();
}
while (isdigit(tmp)) ans = (ans << 1) + (ans << 3) + (tmp ^ 48), tmp = getc();
return ans * flag;
}
int n, rt, cur, g[N], tot;
struct KDTNode {
int x, y, z;
long long v;
int siz, l, r, L, R, D, U, F, B, d;
long long sum;
} w[N];
inline long long max(long long a, long long b, long long c) { return max(a, max(b, c)); }
inline void pushup(int u) {
int ls = lc(u), rs = rc(u);
w[u].siz = w[ls].siz + w[rs].siz + 1;
w[u].sum = max(w[ls].sum, w[rs].sum, w[u].v);
w[u].L = w[u].R = w[u].x;
w[u].U = w[u].D = w[u].y;
w[u].B = w[u].F = w[u].z;
if (lc(u)) {
w[u].L = min(w[u].L, w[ls].L), w[u].R = max(w[u].R, w[ls].R);
w[u].D = min(w[u].D, w[ls].D), w[u].U = max(w[u].U, w[ls].U);
w[u].B = min(w[u].B, w[ls].B), w[u].F = max(w[u].F, w[ls].F);
}
if (rc(u)) {
w[u].L = min(w[u].L, w[rs].L), w[u].R = max(w[u].R, w[rs].R);
w[u].D = min(w[u].D, w[rs].D), w[u].U = max(w[u].U, w[rs].U);
w[u].B = min(w[u].B, w[rs].B), w[u].F = max(w[u].F, w[rs].F);
}
}
inline bool canrebuild(int u) { return alpha * w[u].siz <= (double)max(w[lc(u)].siz, w[rc(u)].siz); }
inline bool cmp1(int x, int y) { return w[x].x < w[y].x; }
inline bool cmp2(int x, int y) { return w[x].y < w[y].y; }
inline bool cmp3(int x, int y) { return w[x].z < w[y].z; }
int build(int l, int r) {
if (l > r) return 0;
int mid = l + r >> 1;
double av1 = 0, av2 = 0, av3 = 0, va1 = 0, va2 = 0, va3 = 0;
for (int i = l; i <= r; i++) av1 += w[g[i]].x, av2 += w[g[i]].y, av3 += w[g[i]].z;
av1 /= r - l + 1;
av2 /= r - l + 1;
av3 /= r - l + 1;
for (int i = l; i <= r; i++)
va1 += sqr(w[g[i]].x - av1), va2 += sqr(w[g[i]].y - av2), va3 += sqr(w[g[i]].z - av3);
if (va1 > va2 && va1 > va3)
nth_element(g + l, g + mid, g + r + 1, cmp1), w[g[mid]].d = 1;
else if (va2 > va3)
nth_element(g + l, g + mid, g + r + 1, cmp2), w[g[mid]].d = 2;
else
nth_element(g + l, g + mid, g + r + 1, cmp3), w[g[mid]].d = 3;
lc(g[mid]) = build(l, mid - 1), rc(g[mid]) = build(mid + 1, r);
pushup(g[mid]);
return g[mid];
}
void dfs(int u) {
if (!u) return;
dfs(lc(u));
g[++tot] = u;
dfs(rc(u));
}
inline void rebuild(int &u) {
tot = 0;
dfs(u);
u = build(1, tot);
}
int needpush;
void insert(int &u) {
if (!u) {
u = needpush, w[u].d = 2;
pushup(u);
return;
}
if (w[u].d == 1) {
if (w[needpush].x <= w[u].x)
insert(lc(u));
else
insert(rc(u));
} else if (w[u].d == 2) {
if (w[needpush].y <= w[u].y)
insert(lc(u));
else
insert(rc(u));
} else {
if (w[needpush].z <= w[u].z)
insert(lc(u));
else
insert(rc(u));
}
pushup(u);
if (canrebuild(u)) rebuild(u);
}
int xl, xr, yl, yr, zl, zr;
long long nowans;
void query(int u) {
if (nowans >= w[u].sum) return;
if (!u || xr < w[u].L || yr < w[u].D || zr < w[u].B) return;
if (w[u].R <= xr && w[u].U <= yr && w[u].F <= zr) {
nowans = max(nowans, w[u].sum);
return;
}
if (w[u].x <= xr && w[u].y <= yr && w[u].z <= zr) nowans = max(nowans, w[u].v);
if (w[lc(u)].sum > w[rc(u)].sum)
query(lc(u)), query(rc(u));
else
query(rc(u)), query(lc(u));
}
const int P = 1e8 + 10;
struct Node {
int x, y, z, k;
long long w;
inline void gread() { x = read(), y = read(), z = read(), k = read(), w = read(), x += P, y += P, z += P, k += P; }
inline bool operator<(const Node &b) const { return x != b.x ? x < b.x : (y != b.y ? y < b.y : (z != b.z ? z < b.z : k < b.k)); }
} a[N], ga[N];
long long f[N];
int main() {
cin >> n;
int cnt = 0;
long long maxn = -0x3f3f3f3f3f3f3f3f;
for (int i = 1; i <= n; i++) {
a[i].gread();
if (a[i].w <= 0)
maxn = max(maxn, a[i].w);
else
ga[++cnt] = a[i];
}
n = cnt;
sort(ga + 1, ga + cnt + 1);
for (int i = 1; i <= n; i++) {
xl = 1, xr = ga[i].y, yl = 1, yr = ga[i].z, zl = 1, zr = ga[i].k;
nowans = 0, query(rt);
maxn = max(maxn, f[i] = ga[i].w + nowans);
w[++cur] = {ga[i].y, ga[i].z, ga[i].k, f[i]};
needpush = cur, insert(rt);
}
cout << maxn;
return 0;
}