题意:输入一颗二叉树的中序,先序,q个询问,每次询问两个节点的lca。
思路:求dfs序,st表维护dfs序中的高度,map映射一下每个值对应的节点序号,rmq求lca。预处理查询
代码
#include #include #include #include #include #include using namespace std; const int MAX_N = 10010; int n, m, r, x, y; int lc[MAX_N], rc[MAX_N], pre[MAX_N], in[MAX_N], fs[MAX_N]; int dfsorder[MAX_N<<2], height[MAX_N<<2], len = 0; map mp; int build(int il, int ir, int pl, int pr) { if (il >= ir) return -1; if (ir - il == 1) return pl; int rt = pl, p = -1; for (int i = il; i < ir; i++) { if (in[i] == pre[rt]) { p = i; break; } } lc[rt] = build(il, p, pl+1, pl+1+p-il); rc[rt] = build(p+1, ir, pl+1+p-il, pr); return rt; } void dfs(int rt, int h) { if (rt == -1) return ; fs[rt] = len; dfsorder[len] = rt; height[len] = h; len++; if (lc[rt] != -1) {dfs(lc[rt], h+1); dfsorder[len] = rt; height[len] = h; len++;} if (rc[rt] != -1) {dfs(rc[rt], h+1); dfsorder[len] = rt; height[len] = h; len++;} } int st[MAX_N<<1][30]; void init(int size) { for (int i = 0; i < size; i++) st[i][0] = i; for (int j = 1; 1< height[a]) return a; else return b; } int lca(int x, int y) { int l = fs[x]; int r = fs[y]; if (l > r) swap(l, r); return pre[dfsorder[rmq(l, r)]]; } int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); memset(lc, -1, sizeof(lc)); memset(rc, -1, sizeof(rc)); memset(fs, -1, sizeof(fs)); scanf("%d %d", &m, &n); for (int i = 0; i < n; i++) scanf("%d", &in[i]); for (int i = 0; i < n; i++) {scanf("%d", &pre[i]); mp[pre[i]] = i;} r = build(0, n, 0, n); dfs(r, 0); init(len); for (int i = 0; i < m; i++) { scanf("%d %d", &x, &y); if (mp.count(x) && mp.count(y)) { int id1 = mp[x], id2 = mp[y]; int res = lca(id1, id2); if (res == x) printf("%d is an ancestor of %d.\n", x, y); else if (res == y) printf("%d is an ancestor of %d.\n", y, x); else printf("LCA of %d and %d is %d.\n", x, y, res); } else { if (mp.count(x)) printf("ERROR: %d is not found.\n", y); else if (mp.count(y)) printf("ERROR: %d is not found.\n", x); else { printf("ERROR: %d and %d are not found.\n", x, y); } } } return 0; }
代码(暴力也能过)
#include #include #include #include #include #include using namespace std; const int MAX_N = 10010; int n, m, x, y, r; int in[MAX_N], pre[MAX_N], lc[MAX_N], rc[MAX_N]; map mp; int build(int il, int ir, int pl, int pr) { if (il >= ir) return -1; if (ir - il == 1) return pl; int rt = pl, p = -1; for (int i = il; i < ir; i++) { if (in[i] == pre[rt]) { p = i; break; } } lc[rt] = build(il, p, pl+1, pl+1+p-il); rc[rt] = build(p+1, ir, pl+1+p-il, pr); return rt; } void lca(int x, int y) { int p = r, v = pre[r]; int tx = mp[x], ty = mp[y]; for(;;) { int tp = mp[v]; if ((tx < tp && tp < ty) || (ty < tp && tp < tx)) { printf("LCA of %d and %d is %d.\n", x, y, v); return ; } else if (tx < tp && ty < tp) { p = lc[p]; v = pre[p]; } else if (tx > tp && ty > tp) { p = rc[p]; v = pre[p]; } else if (tx == tp) { printf("%d is an ancestor of %d.\n", x, y); return ; } else if (ty == tp) { printf("%d is an ancestor of %d.\n", y, x); return ; } } } int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); scanf("%d %d", &m, &n); memset(lc, -1, sizeof(lc)); memset(rc, -1, sizeof(rc)); for (int i = 0; i < n; i++) { scanf("%d", &in[i]); mp[in[i]] = i; } for (int i = 0; i < n; i++) scanf("%d", &pre[i]); r = build(0, n, 0, n); for (int i = 0; i < m; i++) { scanf("%d %d", &x, &y); if (!mp.count(x) && !mp.count(y)) { printf("ERROR: %d and %d are not found.\n", x, y); } else if (!mp.count(x)) { printf("ERROR: %d is not found.\n", x); } else if (!mp.count(y)) { printf("ERROR: %d is not found.\n", y); } else { lca(x, y); } } return 0; }