用
K
D
−
t
r
e
e
KD - tree
KD−tree 维护一个矩阵最值、单点查询、矩阵和
支持矩阵覆盖,满足了树套树无法
p
u
s
h
d
o
w
n
pushdown
pushdown 的短处
矩阵覆盖、查询矩阵最值
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 2e6 + 5;
const double alpha = 0.75;
int n, m, rt, tot, now, ans;
struct node{
int pla[2], val;
} a[maxn];
struct tree{
int mx[2], mn[2], sz, ls, rs;
int lz, val, ans;
node place;
} t[maxn];
inline int New(){
return ++tot;
}
inline bool cmp(const node &A, const node &B){
return A.pla[now] < B.pla[now];
}
inline void update(int p){
for(int i=0; i<=1; i++){
t[p].mx[i] = t[p].mn[i] = t[p].place.pla[i];
if(t[p].ls) t[p].mx[i] = max(t[p].mx[i], t[t[p].ls].mx[i]), \
t[p].mn[i] = min(t[p].mn[i], t[t[p].ls].mn[i]);
if(t[p].rs) t[p].mx[i] = max(t[p].mx[i], t[t[p].rs].mx[i]), \
t[p].mn[i] = min(t[p].mn[i], t[t[p].rs].mn[i]);
}
t[p].ans = max(t[p].ans, max(t[t[p].ls].ans, t[t[p].rs].ans));
// t[p].sz = t[t[p].ls].sz + t[t[p].rs].sz + 1;
}
inline int build(int l, int r, int opt){
if(l > r) return 0;
int x = New(), mid = l + r >> 1; now = opt;
nth_element(a+l, a+mid, a+r+1, cmp);
t[x].place = a[mid], t[x].lz = 0;
t[x].val = t[x].ans = a[mid].val;
t[x].ls = build(l, mid-1, opt^1);
t[x].rs = build(mid+1, r, opt^1);
update(x); return x;
}
inline void pushdown(int p){
if(!t[p].lz) return;
if(t[p].ls) t[t[p].ls].lz = t[t[p].ls].val = t[t[p].ls].ans = t[p].lz;
if(t[p].rs) t[t[p].rs].lz = t[t[p].rs].val = t[t[p].rs].ans = t[p].lz;
t[p].lz = 0;
}
inline void update(int p, int x1, int y1, int x2, int y2, int w){
if(t[p].mx[0]<x1 || t[p].mn[0]>x2) return;
if(t[p].mx[1]<y1 || t[p].mn[1]>y2) return;
pushdown(p);
if(t[p].place.pla[0]>=x1 && t[p].place.pla[0]<=x2 \
&& t[p].place.pla[1]>=y1 && t[p].place.pla[1]<=y2)
t[p].val = t[p].ans = w;
if(t[p].mn[0]>=x1 && t[p].mx[0]<=x2 \
&& t[p].mn[1]>=y1 && t[p].mx[1]<=y2){
t[p].lz = t[p].val = t[p].ans = w;
return;
}
if(t[p].ls) update(t[p].ls, x1, y1, x2, y2, w);
if(t[p].rs) update(t[p].rs, x1, y1, x2, y2, w);
t[p].ans = max(t[p].ans, max(t[t[p].ls].ans, t[t[p].rs].ans));
}
inline void query(int p, int x1, int y1, int x2, int y2){
if(!p || t[p].ans<ans) return ;
if(t[p].mx[0]<x1 || t[p].mn[0]>x2) return ;
if(t[p].mx[1]<y1 || t[p].mn[1]>y2) return ;
pushdown(p);
if(t[p].place.pla[0]>=x1 && t[p].place.pla[0]<=x2 \
&& t[p].place.pla[1]>=y1 && t[p].place.pla[1]<=y2)
ans = max(ans, t[p].val);
query(t[p].ls, x1, y1, x2, y2);
query(t[p].rs, x1, y1, x2, y2);
}
int main() {
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++){
scanf("%d", &a[(i-1)*n+j].val);
a[(i-1)*n+j].pla[0] = i;
a[(i-1)*n+j].pla[1] = j;
}
rt = build(1, n*n, 0);
for(int i=1; i<=m; i++){
int x1, y1, x2, y2, w, op;
scanf("%d", &op);
if(op == 1){
scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &w);
update(rt, x1, y1, x2, y2, w);
} else {
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
ans = 0; query(rt, x1, y1, x2, y2);
printf("%d\n", ans);
}
}
}
单点加、查询矩阵和
例题:bzoj-4066 简单题
注意也可用 二维线段树 做
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const int maxn = 2e5 + 5;
int n, m, rt, tot, now, ans, cnt;
int sta[maxn], top;
struct node{
int pla[2], val;
} a[maxn];
struct tree{
int mx[2], mn[2], sz, ls, rs;
int val, sum;
node place;
} t[maxn];
inline int New(){
if(top) return sta[top--];
return ++tot;
}
inline bool cmp(const node &A, const node &B){
return A.pla[now] < B.pla[now];
}
inline void update(int p){
for(int i=0; i<=1; i++){
t[p].mx[i] = t[p].mn[i] = t[p].place.pla[i];
if(t[p].ls) t[p].mx[i] = max(t[p].mx[i], t[t[p].ls].mx[i]), \
t[p].mn[i] = min(t[p].mn[i], t[t[p].ls].mn[i]);
if(t[p].rs) t[p].mx[i] = max(t[p].mx[i], t[t[p].rs].mx[i]), \
t[p].mn[i] = min(t[p].mn[i], t[t[p].rs].mn[i]);
}
t[p].sum = t[t[p].ls].sum + t[t[p].rs].sum + t[p].val; // 注意是更新!!
t[p].sz = t[t[p].ls].sz + t[t[p].rs].sz + 1;
}
inline int build(int l, int r, int opt){
if(l > r) return 0;
int x = New(), mid = l + r >> 1; now = opt;
nth_element(a+l, a+mid, a+r+1, cmp);
t[x].place = a[mid], t[x].val = t[x].sum = a[mid].val;
t[x].ls = build(l, mid-1, opt^1);
t[x].rs = build(mid+1, r, opt^1);
update(x); return x;
}
inline void pia(int p, int cnt){
if(t[p].ls) pia(t[p].ls, cnt);
a[cnt+t[t[p].ls].sz+1] = t[p].place, sta[++top] = p;
if(t[p].rs) pia(t[p].rs, cnt+t[t[p].ls].sz+1);
}
inline void check(int &p, int opt){
if(t[p].sz*0.75<t[t[p].ls].sz || t[p].sz*0.75<t[t[p].rs].sz)
pia(p, 0), p = build(1, t[p].sz, opt);
}
inline void insert(node ret, int &p, int opt){
if(!p){
p = New(); t[p].place = ret;
t[p].val = t[p].sum = ret.val;
t[p].ls = t[p].rs = 0;
update(p); return;
}
if(ret.pla[opt] <= t[p].place.pla[opt]) insert(ret, t[p].ls, opt^1);
else insert(ret, t[p].rs, opt^1);
update(p); check(p, opt);
}
inline int query(int p, int x1, int y1, int x2, int y2){
if(!p) return 0;
if(t[p].mx[0]<x1 || t[p].mn[0]>x2) return 0;
if(t[p].mx[1]<y1 || t[p].mn[1]>y2) return 0;
if(t[p].mn[0]>=x1 && t[p].mx[0]<=x2 \
&& t[p].mn[1]>=y1 && t[p].mx[1]<=y2)
return t[p].sum;
int ret = 0;
if(t[p].place.pla[0]>=x1 && t[p].place.pla[0]<=x2 \
&& t[p].place.pla[1]>=y1 && t[p].place.pla[1]<=y2)
ret += t[p].val;
ret += query(t[p].ls, x1, y1, x2, y2);
ret += query(t[p].rs, x1, y1, x2, y2);
return ret;
}
signed main() {
scanf("%d", &n);
int op, x1, y1, x2, y2, lans = 0;
while(true){
scanf("%d", &op);
if(op == 1){
cnt++;
scanf("%d%d%d", &a[cnt].pla[0], &a[cnt].pla[1], &a[cnt].val);
a[cnt].pla[0] ^= lans, a[cnt].pla[1] ^= lans, a[cnt].val ^= lans;
insert(a[cnt], rt, 0);
// if(cnt % 10000 == 0) tot = 0, rt = build(1, cnt, 0);
} else if(op == 2){
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
x1 ^= lans, y1 ^= lans, x2 ^= lans, y2 ^= lans;
printf("%d\n", lans = query(rt, x1, y1, x2, y2));
} else break;
}
}
矩阵覆盖、查询单点
例题:bzoj-4154 Generating Synergy
大意是一个树,将一个结点距离不超过
l
l
l 的子节点全部染色,然后查询单个结点的颜色
因此一个点的第一维是
d
f
s
dfs
dfs 序,第二维是深度,即可转化为二维平面上的问题
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
const double alpha = 0.75;
int n, rt, tot, now;
int T, c, q, dfntot;
int dfn[maxn], out[maxn], dep[maxn];
vector <int> g[maxn];
struct node{
int pla[2], val;
} a[maxn];
struct tree{
int mx[2], mn[2], sz, ls, rs;
int lz, val, ans;
node place;
} t[maxn];
inline int New(){
return ++tot;
}
inline bool cmp(const node &A, const node &B){
return A.pla[now] < B.pla[now];
}
inline void update(int p){
for(int i=0; i<=1; i++){
t[p].mx[i] = t[p].mn[i] = t[p].place.pla[i];
if(t[p].ls) t[p].mx[i] = max(t[p].mx[i], t[t[p].ls].mx[i]), \
t[p].mn[i] = min(t[p].mn[i], t[t[p].ls].mn[i]);
if(t[p].rs) t[p].mx[i] = max(t[p].mx[i], t[t[p].rs].mx[i]), \
t[p].mn[i] = min(t[p].mn[i], t[t[p].rs].mn[i]);
}
// t[p].sz = t[t[p].ls].sz + t[t[p].rs].sz + 1;
}
inline int build(int l, int r, int opt){
if(l > r) return 0;
int x = New(), mid = l + r >> 1; now = opt;
nth_element(a+l, a+mid, a+r+1, cmp);
t[x].place = a[mid], t[x].val = a[mid].val, t[x].lz = 0;
t[x].ls = build(l, mid-1, opt^1);
t[x].rs = build(mid+1, r, opt^1);
update(x); return x;
}
inline void pushdown(int p){
if(!t[p].lz) return;
if(t[p].ls) t[t[p].ls].lz = t[t[p].ls].val = t[p].lz;
if(t[p].rs) t[t[p].rs].lz = t[t[p].rs].val = t[p].lz;
t[p].lz = 0;
}
inline void update(int p, int x1, int y1, int x2, int y2, int w){
if(!p) return;
if(t[p].mx[0]<x1 || t[p].mn[0]>x2) return;
if(t[p].mx[1]<y1 || t[p].mn[1]>y2) return;
pushdown(p);
if(t[p].place.pla[0]>=x1 && t[p].place.pla[0]<=x2 \
&& t[p].place.pla[1]>=y1 && t[p].place.pla[1]<=y2)
t[p].val = w;
if(t[p].mn[0]>=x1 && t[p].mx[0]<=x2 \
&& t[p].mn[1]>=y1 && t[p].mx[1]<=y2){
t[p].lz = t[p].val = w;
return;
}
if(t[p].ls) update(t[p].ls, x1, y1, x2, y2, w);
if(t[p].rs) update(t[p].rs, x1, y1, x2, y2, w);
}
inline int query(int p, int x1, int y1, int x2, int y2){
if(!p) return 0;
if(t[p].mx[0]<x1 || t[p].mn[0]>x2) return 0;
if(t[p].mx[1]<y1 || t[p].mn[1]>y2) return 0;
pushdown(p);
if(t[p].place.pla[0]>=x1 && t[p].place.pla[0]<=x2 \
&& t[p].place.pla[1]>=y1 && t[p].place.pla[1]<=y2)
return t[p].val;
int ret = 0;
ret = max(ret, query(t[p].ls, x1, y1, x2, y2));
ret = max(ret, query(t[p].rs, x1, y1, x2, y2));
return ret;
}
void dfs(int u, int de){
dfn[u] = ++dfntot, dep[u] = de, a[u].val = 1;;
a[u].pla[0] = dfn[u], a[u].pla[1] = de;
// for(auto v : g[u]) dfs(v, de+1);
for(int v=0; v<g[u].size(); v++) dfs(g[u][v], de+1);
out[u] = dfntot;
}
int main() {
scanf("%d", &T);
while(T--){
scanf("%d%d%d", &n, &c, &q);
for(int i=1; i<=n; i++) g[i].clear();
for(int i=2, f; i<=n; i++){
scanf("%d", &f);
g[f].push_back(i);
}
dfntot = 0; dfs(1, 0); tot = 0;
rt = build(1, n, 0);
int qa, ql, qc, ans = 0;
for(int i=1; i<=q; i++) {
scanf("%d%d%d", &qa, &ql, &qc);
if(qc) update(rt, dfn[qa], dep[qa], out[qa], dep[qa]+ql, qc);
else {
int tans = query(rt, dfn[qa], dep[qa], dfn[qa], dep[qa]);
ans = (1ll * tans * i % mod + ans) % mod;
}
}
printf("%d\n", ans);
}
}