矩陣覆蓋 查詢最值 查矩陣和 —— KD - tree

KDtreeKD - tree 維護一個矩陣最值、單點查詢、矩陣和
支持矩陣覆蓋,滿足了樹套樹無法 pushdownpushdown 的短處


矩陣覆蓋、查詢矩陣最值

#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
大意是一個樹,將一個結點距離不超過 ll 的子節點全部染色,然後查詢單個結點的顏色
因此一個點的第一維是 dfsdfs 序,第二維是深度,即可轉化爲二維平面上的問題

#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);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章