hs_black
2020-02-29 13:03:22
做kd-tree题找到了这道题 顺便推销blog
这题是四维意义下的最长上升子序列, 但如果将第一维排序就变成三维问题了, kd-tree时间复杂度应该会更优
总而言之就是
从前向后扫, 找到三维都比它小的dp值最大的点, 找点可以用kd-tree来优化
可以采用以下技巧和剪枝:
有了以上剪枝, 足够通过此题
这里有一些数据可能对你有用 可以修改url找到其他数据 从18998到19003
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define I inline
#define ll long long
using namespace std;
template <typename T>
void read(T &x) {
x = 0; bool f = 0;
char c = getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
for (;isdigit(c);c=getchar()) x=x*10+(c^48);
if (f) x=-x;
}
const int N = 200500;
struct node {
int d[4];
bool operator < (const node &k) const {
for (int i = 0;i < 4; i++)
if (d[i] != k.d[i]) return d[i] < k.d[i];
return 0;
}
}p[N];
int g[N], k;
I bool cmp(int a, int b) {
return p[a].d[k] < p[b].d[k];
}
#define ls son[x][0]
#define rs son[x][1]
int son[N][2];
int mx[N][3], mn[N][3], mxa[N], res[N], ans;
I void Mn(int &x, int y) { if (x > y) x = y; }
I void Mx(int &x, int y) { if (x < y) x = y; }
I void maintain(int x) {
for (int i = 0;i <= 2; i++) {
mx[x][i] = mn[x][i] = p[x].d[i+1];
if (ls) Mx(mx[x][i], mx[ls][i]), Mn(mn[x][i], mn[ls][i]);
if (rs) Mx(mx[x][i], mx[rs][i]), Mn(mn[x][i], mn[rs][i]);
}
}
int build(int l, int r, int d) {
if (l > r) return 0;
int mid = (l + r) >> 1;
k = d + 1, nth_element(g + l, g + mid, g + r + 1, cmp);
son[g[mid]][0] = build(l, mid - 1, (d + 1) % 3);
son[g[mid]][1] = build(mid + 1, r, (d + 1) % 3);
maintain(g[mid]); return g[mid];
}
int tmp;
// 判断x点是否在y点范围以内
inline bool in(int *x, int *y) {
int cnt = 0;
for (int i = 0;i < 3; i++) cnt += (x[i] <= y[i]);
return cnt == 3;
}
void query(int x, int y) {
if (mxa[x] <= tmp) return;
if (!in(mn[x], p[y].d + 1)) return;
if (in(mx[x], p[y].d + 1)) return tmp = mxa[x], void();
if (in(p[x].d + 1, p[y].d + 1)) Mx(tmp, res[x]);
if (ls) query(ls, y); if (rs) query(rs, y);
}
// 激活操作
void upit(int x, int y) {
if (x == y) {
res[x] = tmp, Mx(mxa[x], res[x]); return;
}
if (!in(p[y].d + 1, mx[x]) || !in(mn[x], p[y].d + 1)) return;
// 如果y点不在里面就返回
if (ls) upit(ls, y); if (rs) upit(rs, y);
Mx(mxa[x], mxa[ls]), Mx(mxa[x], mxa[rs]);
}
int rt, n;
int main() {
freopen ("hs.in","r",stdin);
read(n);
for (int i = 1;i <= n; i++) {
read(p[i].d[0]), read(p[i].d[1]);
read(p[i].d[2]), read(p[i].d[3]);
g[i] = i;
}
sort(p + 1, p + n + 1); rt = build(1, n, 0);
for (int i = 1;i <= n; i++)
tmp = 0, query(rt, i), tmp++, upit(rt, i), Mx(ans, tmp);
cout << ans << endl;
return 0;
}