K-D tree是一棵平衡二叉树。
K_D即K-Dimention,k维的意思。
可能维护什么k维偏序。
建树的过程中每次会把一堆点按照某一维切半,中间的提出来作根,分成两个部分作为左右子树继续建树。
一个比较劣的维度选法是循环选取,雨露均沾。
也可以随机钦点。
正统的K-D tree是选方差最大的那一维。
复杂度: O ( k n l o g n ) O(k~n~log~n) O(k n log n)
相当于把一个k维空间切切切,没有交集就退,完全包含就直接更新答案。
一次查询复杂度据说是 O ( n 1 − 1 k ) O(n^{1-{1 \over k}}) O(n1−k1)
就是在tree上走到对应的位置,插进去就好了。
如果题目不是强制在线的,可以预先把所有的点建树,然后打tag来表示这个点有没有开启。
插入过多会导致平衡树不平衡,利用替罪羊树的思想重构就好了。
例题:
bzoj 3489: A simple rmq problem
Code:
#include
#include
#include
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define fd(i, x, y) for(int i = x; i >= y; i --)
#define cmin(a, b) (a > b ? a = b : b)
#define cmax(a, b) (a < b ? a = b : b)
#define ls t[o].s[0]
#define rs t[o].s[1]
#define ll long long
using namespace std;
const int N = 1e5 + 5;
int n, m, x, y, la[N], c[N];
int D, rt;
struct no { int d[3];} a[N];
int cmp(no a, no b) {return a.d[D] < b.d[D];}
struct nod { int s[2], d[3], ma[3], mi[3], mx;
void mer(nod a) {
cmax(mx, a.mx);
fo(i, 0, 2) cmax(ma[i], a.ma[i]), cmin(mi[i], a.mi[i]);
}
} t[N];
ll s1[3], s2[3];
int get(int x, int y) {
fo(i, 0, 2) s1[i] = s2[i] = 0;
fo(i, x, y) fo(j, 0, 2) s1[j] += (ll) a[i].d[j] * a[i].d[j], s2[j] += a[i].d[j];
fo(j, 0, 2) s1[j] = s1[j] * (y - x + 1) - s2[j] * s2[j];
return s1[0] > s1[1] ? (s1[0] > s1[2] ? 0 : 2) : (s1[1] > s1[2] ? 1 : 2);
}
void bt(int &v, int x, int y) {
int o = x + y >> 1; v = o; D = get(x, y);
nth_element(a + x, a + o, a + y + 1, cmp);
t[o].mx = c[a[o].d[0]];
fo(j, 0, 2) t[o].ma[j] = t[o].mi[j] = a[o].d[j];
if(x < o) bt(ls, x, o - 1), t[o].mer(t[ls]);
if(o < y) bt(rs, o + 1, y), t[o].mer(t[rs]);
}
int ans, u0, d0, u1, d2;
void get(int o) {
if(t[o].ma[0] < d0 || t[o].mi[0] > u0 || t[o].mi[1] > u1 || t[o].ma[2] < d2 || t[o].mx < ans) return;
if(t[o].mi[0] >= d0 && t[o].ma[0] <= u0 && t[o].ma[1] <= u1 && t[o].mi[2] >= d2) {
ans = t[o].mx; return;
}
if(a[o].d[0] >= d0 && a[o].d[0] <= u0 && a[o].d[1] <= u1 && a[o].d[2] >= d2) cmax(ans, c[a[o].d[0]]);
if(t[ls].mx > t[rs].mx) get(ls), get(rs); else get(rs), get(ls);
}
int main() {
scanf("%d %d", &n, &m);
fo(i, 1, n) {
scanf("%d", &c[i]);
a[i].d[0] = i;
a[la[c[i]]].d[2] = i;
a[i].d[1] = la[c[i]];
la[c[i]] = i;
}
fo(i, 1, n) a[la[i]].d[2] = n + 1;
bt(rt, 1, n);
fo(ii, 1, m) {
scanf("%d %d", &x, &y);
x = (x + ans) % n + 1; y = (y + ans) % n + 1;
if(x > y) swap(x, y);
ans = 0;
d0 = x; u0 = y; u1 = x - 1; d2 = y + 1;
get(rt);
printf("%d\n", ans);
}
}