Série: Algorithms
cpp
142 linhas
· Atualizado 2026-04-07
748.cpp
Algorithms/748.cpp
// 748 - Dynamic Quad Tree
//
// 實際建立 Quad Tree 並動態維護:
// - build: 根據影像建樹,遇到均勻區域建葉節點,否則遞迴分四象限
// - flip: 沿著根到像素的路徑走(深度 ≤ k ≤ 10)
// 遇到葉節點就拆分(split),翻轉後回溯嘗試收合(collapse)
//
// 每次翻轉只影響路徑上的 O(k) 個節點,非常高效
//
// 四象限定義(對於區域 [nr, nr+sz) × [nc, nc+sz),令 h = sz/2):
// ch[0] = NW: [nr, nr+h) × [nc, nc+h)
// ch[1] = NE: [nr, nr+h) × [nc+h, nc+sz)
// ch[2] = SW: [nr+h, nr+sz) × [nc, nc+h)
// ch[3] = SE: [nr+h, nr+sz) × [nc+h, nc+sz)
#include <iostream>
using namespace std;
const int MAXN = 1025;
const int MAXPOOL = 1500000;
struct Node {
int ch[4];
int cnt;
int color;
bool isLeaf;
};
Node pool[MAXPOOL];
int poolCnt;
char grid[MAXN][MAXN];
int newLeaf(int color) {
int id = poolCnt++;
pool[id].ch[0] = pool[id].ch[1] = pool[id].ch[2] = pool[id].ch[3] = -1;
pool[id].cnt = 1;
pool[id].color = color;
pool[id].isLeaf = true;
return id;
}
// 建樹:由上而下,先檢查區域是否均勻
// 均勻 → 葉節點(1 node);否則 → 內部節點 + 遞迴 4 子區域
int build(int r, int c, int sz) {
if (sz == 1) return newLeaf(grid[r][c] - '0');
char first = grid[r][c];
bool uniform = true;
for (int i = r; i < r + sz && uniform; i++)
for (int j = c; j < c + sz && uniform; j++)
if (grid[i][j] != first) uniform = false;
if (uniform) return newLeaf(first - '0');
int id = poolCnt++;
pool[id].isLeaf = false;
int h = sz / 2;
pool[id].ch[0] = build(r, c, h);
pool[id].ch[1] = build(r, c + h, h);
pool[id].ch[2] = build(r + h, c, h);
pool[id].ch[3] = build(r + h, c + h, h);
pool[id].cnt = 1;
for (int q = 0; q < 4; q++)
pool[id].cnt += pool[pool[id].ch[q]].cnt;
return id;
}
// 翻轉像素 (pr, pc),從節點 id(代表區域 [nr,nr+sz)×[nc,nc+sz))開始
void flip(int id, int nr, int nc, int sz, int pr, int pc) {
if (sz == 1) {
pool[id].color ^= 1;
return;
}
// 葉節點被翻轉 → 必須拆分成 4 個同色子節點
if (pool[id].isLeaf) {
pool[id].isLeaf = false;
int c = pool[id].color;
for (int q = 0; q < 4; q++)
pool[id].ch[q] = newLeaf(c);
}
// 判斷像素落在哪個象限
int h = sz / 2;
int ri = (pr >= nr + h) ? 1 : 0;
int ci = (pc >= nc + h) ? 1 : 0;
int q = ri * 2 + ci;
flip(pool[id].ch[q], nr + ri * h, nc + ci * h, h, pr, pc);
// 回溯:嘗試收合(4 個子節點都是同色葉 → 合併為 1 個葉)
bool canCollapse = true;
int fc = pool[pool[id].ch[0]].color;
for (int i = 0; i < 4; i++) {
if (!pool[pool[id].ch[i]].isLeaf || pool[pool[id].ch[i]].color != fc) {
canCollapse = false;
break;
}
}
if (canCollapse) {
pool[id].isLeaf = true;
pool[id].color = fc;
pool[id].cnt = 1;
} else {
pool[id].cnt = 1;
for (int i = 0; i < 4; i++)
pool[id].cnt += pool[pool[id].ch[i]].cnt;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
poolCnt = 0;
int k;
cin >> k;
int n = 1 << k;
for (int i = 0; i < n; i++) cin >> grid[i];
int root = build(0, 0, n);
int m;
cin >> m;
while (m--) {
int r, c;
cin >> r >> c;
r--; c--;
flip(root, 0, 0, n, r, c);
cout << pool[root].cnt << "\n";
}
}
return 0;
}
Artigos relacionados
Algorithms
java
Atualizado 2026-03-02
#include <iostream>.java
#include <iostream>.java — java source code from the Algorithms learning materials (Algorithms/#include <iostream>.java).
Ler artigo →
Algorithms
cpp
Atualizado 2026-04-07
827.cpp
827.cpp — cpp source code from the Algorithms learning materials (Algorithms/827.cpp).
Ler artigo →
Algorithms
cpp
Atualizado 2026-04-07
827_best_greedy.cpp
827_best_greedy.cpp — cpp source code from the Algorithms learning materials (Algorithms/827_best_greedy.cpp).
Ler artigo →
Algorithms
cpp
Atualizado 2026-04-07
8402.cpp
8402.cpp — cpp source code from the Algorithms learning materials (Algorithms/8402.cpp).
Ler artigo →
Algorithms
cpp
Atualizado 2026-04-07
860.cpp
860.cpp — cpp source code from the Algorithms learning materials (Algorithms/860.cpp).
Ler artigo →
Algorithms
cpp
Atualizado 2026-07-24
bin_packing.cpp
bin_packing.cpp — cpp source code from the Algorithms learning materials (Algorithms/Advanced/bin_packing.cpp).
Ler artigo →