题目链接:
[HDU 4429]Split the Rectangle[LCA][二叉树]
题意分析:
Alice和Bob玩游戏,初始时Bob会在左下角坐标为XL,YL,右上角坐标为XR,YR的矩形中绘制线段,给出线段的首尾两个端点,保证每条线段都能将线段所在的矩形划分成更小的两个矩形,问:现在Bob给出Q个查询,每次查询包含两个点,要求删除一些边使得这两个点在同一个矩形中,删除边后必须保证整个图都是矩形,而不存在其它形状的图形,问删除这些边之后最多剩多少矩形?
解题思路:
每个线段都能把矩形切分成更小的两个矩形。二叉树呀= =。把树建完之后,用num[i]数组把i结点的所有子节点个数保存下来,那么每次查询其实就是问这两个点所在的矩形的公共祖先的子结点有多少个?总的答案就是总共的矩形数-祖先的子节点数+1。加1是因为祖先的子节点把自己算进去了。
个人感受:
妙~
具体代码如下:
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<string>
using namespace std;
const int INF = 0x7f7f7f7f;
const int MAXN = 2005;
struct Node {
int lx, ly, rx, ry;
int p, lson, rson, dep;
}node[MAXN];
int num[MAXN]; // 子节点个数
// 确定当前线段在哪个父节点下
int getPos(int p, int x, int y) {
if (node[p].lson == 0) return p;
int l = node[p].lson;
if (node[l].lx <= x && x <= node[l].rx && node[l].ly <= y && y <= node[l].ry)
return getPos(l, x, y);
else return getPos(node[p].rson, x, y);
}
// 计算子节点个数
int getSon(int u) {
num[u] = 0;
if (node[u].lson == 0) return num[u] = 1;
else {
num[u] += getSon(node[u].lson) + getSon(node[u].rson);
}
return num[u];
}
int main()
{
#ifdef LOCAL
freopen("C:\\Users\\apple\\Desktop\\in.txt", "r", stdin);
#endif
int lx, ly, rx, ry, n, q;
while (~scanf("%d%d%d%d", &lx, &ly, &rx, &ry)) {
scanf("%d%d", &n, &q);
int rt = 0, cnt = 1;
node[rt] = (Node){lx, ly, rx, ry, -1, 0, 0, 0};
for (int i = 0; i < n; ++i) {
scanf("%d%d%d%d", &lx, &ly, &rx, &ry);
if (lx > rx) swap(lx, rx);
if (ly > ry) swap(ly, ry);
int mx = (lx + rx) / 2, my = (ly + ry) / 2;
int pos = getPos(0, mx, my);
Node &t = node[pos];
t.lson = cnt;
node[cnt++] = (Node){t.lx, t.ly, rx, ry, pos, 0, 0, t.dep + 1};
t.rson = cnt;
node[cnt++] = (Node){lx, ly, t.rx, t.ry, pos, 0, 0, t.dep + 1};
}
getSon(0);
while (q --) {
scanf("%d%d%d%d", &lx, &ly, &rx, &ry);
int p1 = getPos(0, lx, ly), p2 = getPos(0, rx, ry);
while (p1 != p2) {
if (node[p1].dep < node[p2].dep) p2 = node[p2].p;
else if (node[p1].dep > node[p2].dep) p1 = node[p1].p;
else {
p1 = node[p1].p;
p2 = node[p2].p;
}
}
printf("%d\n", n + 1 - num[p1] + 1);
}
}
return 0;
}