前言
發現自己的樹套樹太菜了
cdq嵌套也太菜了
面對多維的問題直接上天
於是就去學了下K-Dtree,發現不是很難的亞子
K-Dtree的本質就是一顆二叉搜索樹,一般的二叉搜索樹是按數的大小來劃分左右兒子的
K-Dtree就是每次隨機(或者輪換)按照一維來劃分成二叉搜索樹的左右兒子,實現很簡單。
假設現在要把a[i]建成一顆K-Dtree
首先隨便按照a[i]的一維排序。
然後取中間那個作爲根,分成左右部分作爲兩顆子樹,遞歸下去建樹
但是要排序很不優美,c++中有一個好用的stl叫做nth_element,具體的用法是
nth_element(a + l, a + mid, a + r + 1, cmp)
表示的就是a[mid]就是a數組的中位數,比中位數小的在a[l…mid-1],大的在a[mid+1…r]非常方便
建樹就是場這樣
int build(int l, int r, int o) { //o表示按照那一維劃分
if(l > r) return 0;
int mid = (l + r) >> 1;
if(!o) nth_element(a + l, a + mid, a + r + 1, cmp1) ;
else nth_element(a + l, a + mid, a + r + 1, cmp2);//劃分
ch[mid][0] = build(l, mid - 1, o ^ 1);//遞歸下去建樹
ch[mid][1] = build(mid + 1, r, o ^ 1);
update(mid);
return mid;
}
可能會有人問?這樣怎麼就可以保證時間複雜度
其實好像也不能保證,但是基本卡不掉
當然最好就是每一維算出方差,取方差最大的一維來劃分,寫起來麻煩一些而已
這種劃分好像是, D是維數
然後來集體練習一下
這題用K-Dtree的時間複雜度是假的
但是可以當作入門題來練練。
K-Dtree有個重要的地方就是方便剪枝
這題就維護子樹範圍內最大最小的橫縱座標,算可能最大的情況作爲估值
比較左右子樹的估值,哪邊估值大就先往哪邊跑。
如果估值<=已知最大的就沒有必要跑了
code;
#include<bits/stdc++.h>
#define N 1000005
#define int long long
using namespace std;
struct A {
int x, y;
} a[N];
int cmp1(A x, A y) {
return x.x < y.x;
}
int cmp2(A x, A y) {
return x.y < y.y;
}
int L[N], R[N], D[N], U[N], ch[N][2], n, k;
void update(int x) {
L[x] = R[x] = a[x].x;
D[x] = U[x] = a[x].y;
if(ch[x][0]) {
L[x] = min(L[x], L[ch[x][0]]), R[x] = max(R[x], R[ch[x][0]]);
D[x] = min(D[x], D[ch[x][0]]), U[x] = max(U[x], U[ch[x][0]]);
}
if(ch[x][1]) {
L[x] = min(L[x], L[ch[x][1]]), R[x] = max(R[x], R[ch[x][1]]);
D[x] = min(D[x], D[ch[x][1]]), U[x] = max(U[x], U[ch[x][1]]);
}
}
int build(int l, int r, int o) {
if(l > r) return 0;
int mid = (l + r) >> 1;
if(!o) nth_element(a + l, a + mid, a + r + 1, cmp1);
else nth_element(a + l, a + mid, a + r + 1, cmp2);
ch[mid][0] = build(l, mid - 1, o ^ 1);
ch[mid][1] = build(mid + 1, r, o ^ 1);
update(mid);
return mid;
}
int pf(int x) { return x * x;}
int getmax(int x, int y) {
return max(pf(a[x].x - L[y]), pf(a[x].x - R[y])) + max(pf(a[x].y - D[y]), pf(a[x].y - U[y]));
}
priority_queue<int, vector<int>, greater<int> > q;
void query(int l, int r, int id) {
if(l > r) return;
int mid = (l + r) >> 1, t = pf(a[mid].x - a[id].x) + pf(a[mid].y - a[id].y);
if(t > q.top()) q.pop(), q.push(t);
int disl = getmax(id, ch[mid][0]), disr = getmax(id, ch[mid][1]);
if(disl > disr) {
if(disl > q.top()) query(l, mid - 1, id);
if(disr > q.top()) query(mid + 1, r, id);
} else {
if(disr > q.top()) query(mid + 1, r, id);
if(disl > q.top()) query(l, mid - 1, id);
}
}
signed main() {
scanf("%lld%lld", &n, &k); k <<= 1;
for(int i = 1; i <= k; i ++) q.push(0);
for(int i = 1; i <= n; i ++) scanf("%lld%lld", &a[i].x, &a[i].y);
build(1, n, 0);
for(int i = 1; i <= n; i ++) query(1, n, i);
printf("%lld", q.top());
return 0;
}
看代碼能懂。
可以說是四維偏序板子題
cdq套cdq套cdq好像寫起來很麻煩
其他的解法好像也很麻煩
而且要三個log
可以考慮K-Dtree
但是這題還要插入
直接插入的話就會不平衡,考慮如何讓它平衡
K-Dtree是不支持旋轉的,所以可以用類似替罪羊樹的思想拍扁重建
然後就沒了
平衡因子好像比較玄學
code:
#include<bits/stdc++.h>
#define N 1000005
using namespace std;
int mi[N][5], ma[N][5], mf[N], f[N], sz, ch[N][2], size[N], ls[N], tot, dd, root, d[N];
struct T {
int a[5];
} t[N];
void update(int x) {
mi[x][0] = ma[x][0] = t[x].a[0];
mi[x][1] = ma[x][1] = t[x].a[1];
mi[x][2] = ma[x][2] = t[x].a[2];
mf[x] = f[x];
if(ch[x][0]) {
mf[x] = max(mf[x], mf[ch[x][0]]);
for(int i = 0; i < 3; i ++)
mi[x][i] = min(mi[x][i], mi[ch[x][0]][i]),
ma[x][i] = max(ma[x][i], ma[ch[x][0]][i]);
}
if(ch[x][1]) {
mf[x] = max(mf[x], mf[ch[x][1]]);
for(int i = 0; i < 3; i ++)
mi[x][i] = min(mi[x][i], mi[ch[x][1]][i]),
ma[x][i] = max(ma[x][i], ma[ch[x][1]][i]);
}
size[x] = size[ch[x][0]] + size[ch[x][1]] + 1;
}
void dfs(int x) {
if(!x) return;
dfs(ch[x][0]);
ls[++ sz] = x;
dfs(ch[x][1]);
}
int cmpp(int x, int y) {
return t[x].a[dd] < t[y].a[dd];
}
int build(int l, int r, int o) {
if(l > r) return 0;
int mid = (l + r) >> 1;
dd = o;
nth_element(ls + l, ls + mid, ls + r + 1, cmpp);
int rt = ls[mid];
d[rt] = o;
ch[rt][0] = build(l, mid - 1, (o + 1) % 3);
ch[rt][1] = build(mid + 1, r, (o + 1) % 3);
update(rt);
return rt;
}
void rebuild(int &x) {
sz = 0;
dfs(x);
x = build(1, sz, 0);
}
const double alpha = 0.725;
bool bad(int x) {return alpha * size[x] <= (double)max(size[ch[x][0]], size[ch[x][1]]);}
void insert(int &x, int y) {
if(!x) {
x = y;
update(x);
return;
}
if(t[y].a[d[x]] <= t[x].a[d[x]]) insert(ch[x][0], y);
else insert(ch[x][1], y);
update(x);
if(bad(x)) rebuild(x);
}
int ans = 0;
void query(int x, int y) {
if(!x || t[y].a[0] < mi[x][0] || t[y].a[1] < mi[x][1] || t[y].a[2] < mi[x][2]) return ;
if(t[x].a[0] <= t[y].a[0] && t[x].a[1] <= t[y].a[1] && t[x].a[2] <= t[y].a[2])ans = max(ans, f[x]);
if(mf[x] <= ans) return;
if(ma[x][0] <= t[y].a[0] && ma[x][1] <= t[y].a[1] && ma[x][2] <= t[y].a[2]) {
ans = max(ans, mf[x]);
return;
}
query(ch[x][0], y), query(ch[x][1], y);
}
int n;
struct A {
int a[5];
} a[N];
int cmp(A x, A y) {
if(x.a[0] != y.a[0]) return x.a[0] < y.a[0];
if(x.a[1] != y.a[1]) return x.a[1] < y.a[1];
if(x.a[2] != y.a[2]) return x.a[2] < y.a[2];
return x.a[3] < y.a[3];
}
int main() {
srand(time(NULL));
scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%d%d%d%d", &a[i].a[0], &a[i].a[1], &a[i].a[2], &a[i].a[3]);
sort(a + 1, a + 1 + n, cmp);
for(int i = 1; i <= n; i ++) {
t[++ tot] = T{a[i].a[1], a[i].a[2], a[i].a[3]};
ans = 0;
query(root, tot);
f[tot] = ans + 1;
insert(root, tot);
}
ans = 0;
for(int i = 1; i <= n; i ++) ans = max(ans, f[i]);
printf("%d", ans);
return 0;
}
這題關鍵也是在估值函數上
如果子樹最大的x和y都不行就不用進入子樹了
然後就沒了
code:
#include<bits/stdc++.h>
#define N 1000005
#define int long long
using namespace std;
int mi[N][5], ma[N][5], mf[N], f[N], sz, ch[N][2], size[N], ls[N], tot, dd, root, d[N], m, n;
struct T {
int a[5];
} t[N];
void update(int x) {
mi[x][0] = ma[x][0] = t[x].a[0];
mi[x][1] = ma[x][1] = t[x].a[1];
mf[x] = f[x];
if(ch[x][0]) {
mf[x] += mf[ch[x][0]];
for(int i = 0; i < 2; i ++)
mi[x][i] = min(mi[x][i], mi[ch[x][0]][i]),
ma[x][i] = max(ma[x][i], ma[ch[x][0]][i]);
}
if(ch[x][1]) {
mf[x] += mf[ch[x][1]];
for(int i = 0; i < 2; i ++)
mi[x][i] = min(mi[x][i], mi[ch[x][1]][i]),
ma[x][i] = max(ma[x][i], ma[ch[x][1]][i]);
}
size[x] = size[ch[x][0]] + size[ch[x][1]] + 1;
}
void dfs(int x) {
if(!x) return;
dfs(ch[x][0]);
ls[++ sz] = x;
dfs(ch[x][1]);
}
int cmpp(int x, int y) {
return t[x].a[dd] < t[y].a[dd];
}
int build(int l, int r, int o) {
if(l > r) return 0;
int mid = (l + r) >> 1;
dd = o;
nth_element(ls + l, ls + mid, ls + r + 1, cmpp);
int rt = ls[mid];
d[rt] = o;
ch[rt][0] = build(l, mid - 1, (o + 1) % 2);
ch[rt][1] = build(mid + 1, r, (o + 1) % 2);
update(rt);
return rt;
}
int ans = 0;
void query(int x, int a, int b, int c) {
int tt = 0;
tt += ma[x][0] * a + ma[x][1] * b < c;
tt += ma[x][0] * a + mi[x][1] * b < c;
tt += mi[x][0] * a + ma[x][1] * b < c;
tt += mi[x][0] * a + mi[x][1] * b < c;
if(tt == 4) {
ans += mf[x];
return;
}
if(tt == 0) return;
if(a * t[x].a[0] + b * t[x].a[1] < c) ans += f[x];
query(ch[x][0], a, b, c), query(ch[x][1], a, b, c);
}
signed main() {
srand(time(NULL));
scanf("%lld%lld", &n, &m);
for(int i = 1; i <= n; i ++) {
++ tot;
scanf("%lld%lld%lld", &t[tot].a[0], &t[tot].a[1], &f[tot]);
ls[++ sz] = tot;
}
root = build(1, sz, 0);
for(int i = 1; i <= m; i ++) {
ans = 0;
int a, b, c;
scanf("%lld%lld%lld", &a, &b, &c);
query(root, a, b, c);
printf("%lld\n", ans);
}
return 0;
}
這題和第一題有什麼區別???
code:
#include<bits/stdc++.h>
#define N 1000005
#define int long long
using namespace std;
struct A {
int x, y, id;
} a[N];
int cmp1(A x, A y) {
return x.x < y.x;
}
int cmp2(A x, A y) {
return x.y < y.y;
}
int L[N], R[N], D[N], U[N], ch[N][2], n, k, X, Y, m;
void update(int x) {
L[x] = R[x] = a[x].x;
D[x] = U[x] = a[x].y;
if(ch[x][0]) {
L[x] = min(L[x], L[ch[x][0]]), R[x] = max(R[x], R[ch[x][0]]);
D[x] = min(D[x], D[ch[x][0]]), U[x] = max(U[x], U[ch[x][0]]);
}
if(ch[x][1]) {
L[x] = min(L[x], L[ch[x][1]]), R[x] = max(R[x], R[ch[x][1]]);
D[x] = min(D[x], D[ch[x][1]]), U[x] = max(U[x], U[ch[x][1]]);
}
}
int build(int l, int r, int o) {
if(l > r) return 0;//printf(" %d %d\n", l, r);
int mid = (l + r) >> 1;
if(!o) nth_element(a + l, a + mid, a + r + 1, cmp1);
else nth_element(a + l, a + mid, a + r + 1, cmp2);
ch[mid][0] = build(l, mid - 1, o ^ 1);
ch[mid][1] = build(mid + 1, r, o ^ 1);
update(mid);
return mid;
}
int pf(int x) { return x * x;}
int getmax(int y) {
return max(pf(X - L[y]), pf(X - R[y])) + max(pf(Y - D[y]), pf(Y - U[y]));
}
struct AA {
int dis, id;
};
bool operator < (AA x, AA y) {
if(x.dis != y.dis) return x.dis > y.dis;
return x.id < y.id;
}
priority_queue<AA> q;
void query(int x) {
if(!x) return;
int t = pf(a[x].x - X) + pf(a[x].y - Y); //printf(" %d (%d)\n", x, t);
if(t > q.top().dis || (q.top().dis == t && a[x].id < q.top().id)) q.pop(), q.push(AA{t, a[x].id});//, printf("*%d*", t);;
int disl = getmax(ch[x][0]), disr = getmax(ch[x][1]);
if(disl > disr) {
if(disl >= q.top().dis) query(ch[x][0]);
if(disr >= q.top().dis) query(ch[x][1]);
} else {
if(disr >= q.top().dis) query(ch[x][1]);
if(disl >= q.top().dis) query(ch[x][0]);
}
// query(ch[x][0]), query(ch[x][1]);
}
signed main() {
scanf("%lld", &n);
for(int i = 1; i <= n; i ++) scanf("%lld%lld", &a[i].x, &a[i].y), a[i].id = i;
int root = build(1, n, 0);
scanf("%lld", &m);
for(int i = 1; i <= m; i ++) {
scanf("%lld%lld%lld", &X, &Y, &k);
while(q.size()) q.pop();
for(int j = 1; j <= k; j ++) q.push(AA{-1, 0});
query(root);
printf("%lld\n", q.top().id);
}
return 0;
}
和四維偏序那題差不多
多維護一個東西
code:
#include<bits/stdc++.h>
#define N 1000005
#define ll long long
#define mod 998244353
using namespace std;
ll mi[N][5], ma[N][5], mf[N], f[N];
int sz, ch[N][2], size[N], ls[N], tot, dd, root, d[N], ms[N], gs[N];
struct T {
int a[5];
} t[N];
inline void MOD(int &x) {
if(x >= mod) x -= mod;
}
void update(int x) {
mi[x][0] = ma[x][0] = t[x].a[0];
mi[x][1] = ma[x][1] = t[x].a[1];
mi[x][2] = ma[x][2] = t[x].a[2];
mf[x] = f[x];
ms[x] = gs[x];
if(ch[x][0]) {
if(mf[ch[x][0]] == mf[x]) {
ms[x] += ms[ch[x][0]];
MOD(ms[x]);
} else
if(mf[ch[x][0]] > mf[x]) {
mf[x] = mf[ch[x][0]];
ms[x] = ms[ch[x][0]];
}
for(int i = 0; i < 3; i ++)
mi[x][i] = min(mi[x][i], mi[ch[x][0]][i]),
ma[x][i] = max(ma[x][i], ma[ch[x][0]][i]);
}
if(ch[x][1]) {
if(mf[ch[x][1]] == mf[x]) {
ms[x] += ms[ch[x][1]];
MOD(ms[x]);
} else
if(mf[ch[x][1]] > mf[x]) {
mf[x] = mf[ch[x][1]];
ms[x] = ms[ch[x][1]];
}
for(int i = 0; i < 3; i ++)
mi[x][i] = min(mi[x][i], mi[ch[x][1]][i]),
ma[x][i] = max(ma[x][i], ma[ch[x][1]][i]);
}
size[x] = size[ch[x][0]] + size[ch[x][1]] + 1;
}
void dfs(int x) {
if(!x) return;
dfs(ch[x][0]);
ls[++ sz] = x;
dfs(ch[x][1]);
}
int cmpp(int x, int y) {
return t[x].a[dd] < t[y].a[dd];
}
int build(int l, int r, int o) {
if(l > r) return 0;
int mid = (l + r) >> 1;
dd = o;
nth_element(ls + l, ls + mid, ls + r + 1, cmpp);
int rt = ls[mid];
d[rt] = o;
ch[rt][0] = build(l, mid - 1, (o + 1) % 3);
ch[rt][1] = build(mid + 1, r, (o + 1) % 3);
update(rt);
return rt;
}
void rebuild(int &x) {
sz = 0;
dfs(x);
x = build(1, sz, 0);
}
const double alpha = 0.725;
bool bad(int x) {return alpha * size[x] <= (double)max(size[ch[x][0]], size[ch[x][1]]);}
void insert(int &x, int y) {
if(!x) {
x = y;
update(x);
return;
}
if(t[y].a[d[x]] <= t[x].a[d[x]]) insert(ch[x][0], y);
else insert(ch[x][1], y);
update(x);
if(bad(x)) rebuild(x);
}
ll ans = 0;
int anss = 0;
void query(int x, int y) {
if(!x || t[y].a[0] < mi[x][0] || t[y].a[1] < mi[x][1] || t[y].a[2] < mi[x][2]) return ;
if(ma[x][0] <= t[y].a[0] && ma[x][1] <= t[y].a[1] && ma[x][2] <= t[y].a[2]) {
if(mf[x] == ans) anss += ms[x], MOD(anss);
else
if(mf[x] > ans) ans = mf[x], anss = ms[x];
return;
}
if(t[x].a[0] <= t[y].a[0] && t[x].a[1] <= t[y].a[1] && t[x].a[2] <= t[y].a[2]) {
if(f[x] == ans) anss += gs[x], MOD(anss);
else
if(f[x] > ans) ans = f[x], anss = gs[x];
}
if(mf[x] < ans) return;
query(ch[x][0], y), query(ch[x][1], y);
}
int n, m;
struct A {
int a[5]; int val;
} a[N];
int cmp(A x, A y) {
if(x.a[0] != y.a[0]) return x.a[0] < y.a[0];
if(x.a[1] != y.a[1]) return x.a[1] < y.a[1];
if(x.a[2] != y.a[2]) return x.a[2] < y.a[2];
return x.a[3] < y.a[3];
}
int main() {
srand(time(NULL));
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++) scanf("%d%d%d%d%d", &a[i].a[0], &a[i].a[1], &a[i].a[2], &a[i].a[3], &a[i].val);
sort(a + 1, a + 1 + n, cmp);
for(int i = 1; i <= n; i ++) {
t[++ tot] = T{a[i].a[1], a[i].a[2], a[i].a[3]};
ans = 0, anss = 1;
query(root, tot);
f[tot] = ans + a[i].val;
gs[tot] = anss;
insert(root, tot);
}
ans = 0, anss = 0;
for(int i = 1; i <= n; i ++) {
if(ans == f[i]) anss += gs[i], MOD(anss);
else if(f[i] > ans) ans = f[i], anss = gs[i];
}
printf("%lld\n%d", ans, anss);
return 0;
}
維護最大最小就好了
code:
#include<bits/stdc++.h>
#define N 1000005
#define ll long long
using namespace std;
struct A {
int x, y, id;
} a[N];
int cmp1(A x, A y) {
return x.x < y.x;
}
int cmp2(A x, A y) {
return x.y < y.y;
}
int L[N], R[N], D[N], U[N], ch[N][2], n, k, X, Y, m;
void update(int x) {
L[x] = R[x] = a[x].x;
D[x] = U[x] = a[x].y;
if(ch[x][0]) {
L[x] = min(L[x], L[ch[x][0]]), R[x] = max(R[x], R[ch[x][0]]);
D[x] = min(D[x], D[ch[x][0]]), U[x] = max(U[x], U[ch[x][0]]);
}
if(ch[x][1]) {
L[x] = min(L[x], L[ch[x][1]]), R[x] = max(R[x], R[ch[x][1]]);
D[x] = min(D[x], D[ch[x][1]]), U[x] = max(U[x], U[ch[x][1]]);
}
}
int build(int l, int r, int o) {
if(l > r) return 0;
int mid = (l + r) >> 1;
if(!o) nth_element(a + l, a + mid, a + r + 1, cmp1);
else nth_element(a + l, a + mid, a + r + 1, cmp2);
ch[mid][0] = build(l, mid - 1, o ^ 1);
ch[mid][1] = build(mid + 1, r, o ^ 1);
update(mid);
return mid;
}
int ans, anss;
int getmin(int y) {
return max(X - R[y], 0) + max(L[y] - X, 0) + max(Y - U[y], 0) + max(D[y] - Y, 0);
}
int getmax(int y) {
return max(abs(X - L[y]), abs(X - R[y])) + max(abs(Y - D[y]), abs(Y - U[y]));
}
void querymax(int x) {
if(!x) return;
int t = abs(a[x].x - X) + abs(a[x].y - Y);
ans = max(ans, t);
int disl = getmax(ch[x][0]), disr = getmax(ch[x][1]);
if(disl > disr) {
if(disl > ans) querymax(ch[x][0]);
if(disr > ans) querymax(ch[x][1]);
} else {
if(disr > ans) querymax(ch[x][1]);
if(disl > ans) querymax(ch[x][0]);
}
}
void querymin(int x) {
if(!x) return;
int t = abs(a[x].x - X) + abs(a[x].y - Y);
if(t) anss = min(t, anss);
int disl = getmin(ch[x][0]), disr = getmin(ch[x][1]);
if(disl < disr) {
if(disl < anss) querymin(ch[x][0]);
if(disr < anss) querymin(ch[x][1]);
} else {
if(disr < anss) querymin(ch[x][1]);
if(disl < anss) querymin(ch[x][0]);
}
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%d%d", &a[i].x, &a[i].y), a[i].id = i;
int root = build(1, n, 0), ANS = 2147483647;
for(int i = 1; i <= n; i ++) {
X = a[i].x, Y = a[i].y;
ans = 0, anss = 2147483647;
querymax(root), querymin(root);
ANS = min(ANS, ans - anss);
}
printf("%d", ANS);
return 0;
}
單點修改,矩陣求和
其實這個纔是板子題
不過前面也講了,不平衡直接拍扁重建就好了
code:
#include<bits/stdc++.h>
#define N 1000005
using namespace std;
int mi[N][5], ma[N][5], sum[N], sz, f[N], ch[N][2], size[N], ls[N], tot, dd, root, d[N];
struct T {
int a[5];
} t[N];
void update(int x) {
mi[x][0] = ma[x][0] = t[x].a[0];
mi[x][1] = ma[x][1] = t[x].a[1];
sum[x] = f[x];
if(ch[x][0]) {
sum[x] += sum[ch[x][0]];
for(int i = 0; i < 3; i ++)
mi[x][i] = min(mi[x][i], mi[ch[x][0]][i]),
ma[x][i] = max(ma[x][i], ma[ch[x][0]][i]);
}
if(ch[x][1]) {
sum[x] += sum[ch[x][1]];
for(int i = 0; i < 3; i ++)
mi[x][i] = min(mi[x][i], mi[ch[x][1]][i]),
ma[x][i] = max(ma[x][i], ma[ch[x][1]][i]);
}
size[x] = size[ch[x][0]] + size[ch[x][1]] + 1;
}
void dfs(int x) {
if(!x) return;
dfs(ch[x][0]);
ls[++ sz] = x;
dfs(ch[x][1]);
}
int cmpp(int x, int y) {
return t[x].a[dd] < t[y].a[dd];
}
int build(int l, int r, int o) {
if(l > r) return 0;
int mid = (l + r) >> 1;
dd = o;
nth_element(ls + l, ls + mid, ls + r + 1, cmpp);
int rt = ls[mid];
d[rt] = o;
ch[rt][0] = build(l, mid - 1, o ^ 1);
ch[rt][1] = build(mid + 1, r, o ^ 1);
update(rt);
return rt;
}
void rebuild(int &x) {
sz = 0;
dfs(x);
x = build(1, sz, 0);
}
const double alpha = 0.765;
bool bad(int x) {return alpha * size[x] <= (double)max(size[ch[x][0]], size[ch[x][1]]);}
void insert(int &x, int y) {
if(!x) {
x = y;
update(x);
return;
}
if(t[y].a[d[x]] <= t[x].a[d[x]]) insert(ch[x][0], y);
else insert(ch[x][1], y);
update(x);
if(bad(x)) rebuild(x);
}
int lastans = 0, X, Y, XX, YY;
void query(int x) {
if(!x || ma[x][0] < X || mi[x][0] > XX || ma[x][1] < Y || mi[x][1] > YY) return ;
if(X <= mi[x][0] && ma[x][0] <= XX && Y <= mi[x][1] && ma[x][1] <= YY) {lastans += sum[x]; return;}
if(X <= t[x].a[0] && t[x].a[0] <= XX && Y <= t[x].a[1] && t[x].a[1] <= YY) lastans += f[x];
query(ch[x][0]), query(ch[x][1]);
}
int n;
int main() {
scanf("%d", &n);
while(1) {
int opt;
scanf("%d", &opt);
if(opt == 3) return 0;
if(opt == 1) {
++ tot;
scanf("%d%d%d", &t[tot].a[0], &t[tot].a[1], &f[tot]);
t[tot].a[0] ^= lastans, t[tot].a[1] ^= lastans, f[tot] ^= lastans;
insert(root, tot);
} else {
scanf("%d%d%d%d", &X, &Y, &XX, &YY);
X ^= lastans, Y ^= lastans, XX ^= lastans, YY ^= lastans;
lastans = 0;
query(root);
printf("%d\n", lastans);
}
}
return 0;
}
然後就沒了,真是一個神奇的數據結構啊!!!
啊啊啊♂
當然樹套樹和cdq嵌套也是必須要掌握的呢