通過 poj3368 問題討論:RMQ問題的 tarjan_lca 求解
阿新 • • 發佈:2019-01-29
#include <string.h> #include <stdio.h> struct rec_tree { int up, l, r; rec_tree():up(-1), l(-1), r(-1){} }; struct rec_query { int u, qk, e; }; const int maxn = 100005; rec_tree tree[maxn]; rec_query query[3*maxn]; int ans[maxn], head[maxn], a[maxn], nset[maxn], w[maxn], ql[maxn], qr[maxn], father[maxn]; int tot, n, m, q, root; bool vis[maxn]; void init() { memset(head, -1, sizeof(head)); memset(vis, false, sizeof(vis)); tot = 0; m = 0; } void add_query(int u1, int v1, int kv) { query[tot].u = v1; query[tot].qk = kv; query[tot].e = head[u1]; head[u1] = tot++; query[tot].u = u1; query[tot].qk = kv; query[tot].e = head[v1]; head[v1] = tot++; } void readd() { for (int i = 0; i < n; ++i) scanf("%d", &a[i]); int j, k = 0; while (k < n) { j = k; while (j < n && a[j] == a[j+1]) nset[j++] = m; nset[j] = m; w[m++] = j-k+1; k = j+1; } for (int i = 0; i < q; ++i) { scanf("%d%d", &ql[i], &qr[i]); if (nset[ql[i]-1]+1 < nset[qr[i]-1]) add_query(nset[ql[i]-1]+1, nset[qr[i]-1]-1, i); } for (int i = 0; i < m; ++i) tree[i] = rec_tree(); int l = 0, tp; root = 0; for (int i = 1; i < m; ++i) { tree[l].r = i; tree[i].up = l; while (l != -1 && w[i] > w[l]) { tp = tree[l].up; tree[i].up = tree[l].up; if (tree[l].up != -1) tree[tree[l].up].r = i; else root = i; tree[l].up = i; if (tree[i].l == -1) { tree[i].l = l; tree[l].r = -1; } else { k = tree[i].l; tree[i].l = l; tree[l].r = k; tree[k].up = l; } l = tp; } l = i; } for (int i = 0; i < m; ++i) father[i] = i; } int find_fa(int p) { int t = p, kp = p; for (; p != father[p]; p = father[p]); for (; kp != p; t = kp) { kp = father[t]; father[t] = p; } return p; } void tarjan_lca(int p) { if (tree[p].l != -1) { tarjan_lca(tree[p].l); father[tree[p].l] = p; } if (tree[p].r != -1) { tarjan_lca(tree[p].r); father[tree[p].r] = p; } vis[p] = true; int tp = head[p]; while (tp != -1) { if (vis[query[tp].u]) ans[query[tp].qk] = w[find_fa(query[tp].u)]; tp = query[tp].e; } } int main() { scanf("%d", &n); while (n != 0) { scanf("%d", &q); init(); readd(); tarjan_lca(root); for (int i = 1; i < m; ++i) w[i] += w[i-1]; int tm, maxt; for (int i = 0; i < q; ++i) { if (nset[ql[i]-1] == nset[qr[i]-1]) printf("%d\n", qr[i] - ql[i]+1); else if (nset[ql[i]-1]+1 == nset[qr[i]-1]) { maxt = w[nset[ql[i]-1]]-ql[i]+1; if (qr[i]-w[nset[qr[i]-1]-1] > maxt) maxt = qr[i]-w[nset[qr[i]-1]-1]; printf("%d\n", maxt);/*std::max(w[nset[ql[i]-1]]-ql[i]+1, qr[i]-w[nset[qr[i]-1]-1]*/ } else { tm = w[nset[ql[i]-1]]-ql[i]+1; if (qr[i]-w[nset[qr[i]-1]-1] > tm) tm = qr[i]-w[nset[qr[i]-1]-1]; //std::max(w[nset[ql[i]-1]]-ql[i]+1, qr[i]-w[nset[qr[i]-1]-1]); if (ans[i] > tm) tm = ans[i]; printf("%d\n", tm);/*std::max(tm, ans[i])*/ } } scanf("%d",&n); } }