標籤:using style ext 資料 tchar 線段 依次 排序 bool
[hihoCoder#1381]Little Y‘s Tree
試題描述
小Y有一棵n個節點的樹,每條邊都有正的邊權。
小J有q個詢問,每次小J會刪掉這個樹中的k條邊,這棵樹被分成k+1個連通塊。小J想知道每個連通塊中最遠點對距離的和。
這裡的詢問是互相獨立的,即每次都是在小Y的原樹上進行操作。
輸入
第一行一個整數n,接下來n-1行每行三個整數u,v,w,其中第i行表示第i條邊邊權為wi,串連了ui,vi兩點。
接下來一行一個整數q,表示有q組詢問。
對於每組詢問,第一行一個正整數k,接下來一行k個不同的1到n-1之間的整數,表示刪除的邊的編號。
1<=n,q,Σk<=105, 1<=w<=109
輸出
共q行,每行一個整數表示詢問的答案。
輸入樣本
51 2 22 3 32 4 44 5 234 1 2 3 41 42 2 3
輸出樣本
074
資料規模及約定
見“輸入”
題解
我們將每次刪除的所有邊的深度較大的節點作為關鍵點,建立虛樹。然後我們發現我們可以維護一下區間的連通性,將所有節點按照 dfs 序從小到大排序以後,用線段樹合并連通訊息。對於兩個連通塊 A 和 B,若 A 的直徑為 (a, b),B 的直徑為 (c, d),那麼 A U B 的直徑就是 (a, b), (c, d), (a, c), (a, d), (b, c), (b, d) 六種情況,我們去一個最大值即可。對於一顆虛樹,我們按照深度從大到小依次查詢該節點對應區間的連通塊直徑,累計答案,再將這個區間打上刪除標記,最後記得要恢複刪除標記。
對了,這題要 O(1) 求 LCA。
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cctype>#include <algorithm>using namespace std;int read() {int x = 0, f = 1; char c = getchar();while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); }while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); }return x * f;}#define maxn 100010#define maxm 200010#define maxlog 20#define oo 2147483647#define LL long longint n, m, head[maxn], Next[maxm], To[maxm], dist[maxm];struct Edge {int a, b, c;Edge() {}Edge(int _1, int _2, int _3): a(_1), b(_2), c(_3) {}} es[maxn];void AddEdge(int a, int b, int c) {To[++m] = b; dist[m] = c; Next[m] = head[a]; head[a] = m;swap(a, b);To[++m] = b; dist[m] = c; Next[m] = head[a]; head[a] = m;return ;}int dep[maxn], list[maxm], cl, pos[maxn], ord[maxn], clo, ordr[maxn], Pos[maxn];LL Dep[maxn];void build(int u, int fa) {list[++cl] = u; pos[u] = cl; ord[u] = ++clo; Pos[clo] = u;for(int e = head[u]; e; e = Next[e]) if(To[e] != fa) {dep[To[e]] = dep[u] + 1;Dep[To[e]] = Dep[u] + dist[e];build(To[e], u);list[++cl] = u;}ordr[u] = clo;return ;}int Lca[maxlog][maxm], Log[maxm];void rmq_init() {Log[1] = 0;for(int i = 2; i <= cl; i++) Log[i] = Log[i>>1] + 1;for(int i = 1; i <= cl; i++) Lca[0][i] = list[i];for(int j = 1; (1 << j) <= cl; j++)for(int i = 1; i + (1 << j) - 1 <= cl; i++) {int a = Lca[j-1][i], b = Lca[j-1][i+(1<<j-1)];if(dep[a] < dep[b]) Lca[j][i] = a;else Lca[j][i] = b;}return ;}int lca(int a, int b) {int l = min(pos[a], pos[b]), r = max(pos[a], pos[b]);int t = Log[r-l+1];a = Lca[t][l]; b = Lca[t][r-(1<<t)+1];return dep[a] < dep[b] ? a : b;}LL calc(int a, int b) {return Dep[a] + Dep[b] - (Dep[lca(a,b)] << 1);}struct Node {bool hasv;int A, B; LL Len;Node() {}Node(int _1, int _2, LL _3, bool _4): A(_1), B(_2), Len(_3), hasv(_4) {}} ns[maxn<<2];void maintain(Node& o, Node lc, Node rc) {o.Len = -1;if(!lc.hasv && !rc.hasv){ o.Len = o.hasv = 0; return ; }if(!lc.hasv) {o = rc;return ;}if(!rc.hasv) {o = lc;return ;}o.hasv = 1;if(o.Len < lc.Len) o.Len = lc.Len, o.A = lc.A, o.B = lc.B;if(o.Len < rc.Len) o.Len = rc.Len, o.A = rc.A, o.B = rc.B;LL d = calc(lc.A, rc.A);if(o.Len < d) o.Len = d, o.A = lc.A, o.B = rc.A;d = calc(lc.A, rc.B);if(o.Len < d) o.Len = d, o.A = lc.A, o.B = rc.B;d = calc(lc.B, rc.A);if(o.Len < d) o.Len = d, o.A = lc.B, o.B = rc.A;d = calc(lc.B, rc.B);if(o.Len < d) o.Len = d, o.A = lc.B, o.B = rc.B;return ;}void build(int L, int R, int o) {if(L == R) ns[o] = Node(Pos[L], Pos[R], 0, 1);else {int M = L + R >> 1, lc = o << 1, rc = lc | 1;build(L, M, lc); build(M+1, R, rc);maintain(ns[o], ns[lc], ns[rc]);ns[o].hasv = 1;}//printf("seg[%d, %d]: %d %d %lld\n", L, R, ns[o].A, ns[o].B, ns[o].Len);return ;}void update(int L, int R, int o, int ql, int qr, bool v) {if(ql <= L && R <= qr) ns[o].hasv = v;else {int M = L + R >> 1, lc = o << 1, rc = lc | 1;if(ql <= M) update(L, M, lc, ql, qr, v);if(qr > M) update(M+1, R, rc, ql, qr, v);maintain(ns[o], ns[lc], ns[rc]);}return ;}Node query(int L, int R, int o, int ql, int qr) {if(ql <= L && R <= qr) return ns[o];int M = L + R >> 1, lc = o << 1, rc = lc | 1;Node ans(-1, -1, -1, 0);if(ql <= M) {Node tmp = query(L, M, lc, ql, qr), tt(0, 0, -1, 1);maintain(tt, tmp, ans);if(tmp.hasv) ans = tt;}if(qr > M) {Node tmp = query(M+1, R, rc, ql, qr), tt(0, 0, -1, 1);maintain(tt, tmp, ans);if(tmp.hasv) ans = tt;}//printf("[%d, %d] %d %d %d %lld(%d)\nans: %lld\n", L, R, o, ql, qr, ns[o].Len, ns[o].hasv, ans.Len);return ans;}bool cmp(int a, int b) { return pos[a] < pos[b]; }int psi[maxn], cpi, ps[maxn], cp, vis[maxn];bool flg[maxn];struct Vtree {int m, head[maxn], Next[maxm], To[maxm];LL dist[maxm], ans;void init() {ans = m = 0;return ;}void AddEdge(int a, int b, LL c) {//printf("Add2: %d %d %lld\n", a, b, c);To[++m] = b; dist[m] = c; Next[m] = head[a]; head[a] = m;swap(a, b);To[++m] = b; dist[m] = c; Next[m] = head[a]; head[a] = m;return ;}void dfs(int u, int fa) {for(int e = head[u]; e; e = Next[e]) if(To[e] != fa)dfs(To[e], u);if(flg[u]) {Node tmp = query(1, n, 1, ord[u], ordr[u]); flg[u] = 0;if(tmp.hasv) ans += tmp.Len;//printf("at %d tmp: %lld [%d, %d]\n", u, tmp.Len, ord[u], ordr[u]);update(1, n, 1, ord[u], ordr[u], 0);}return ;}void dfs2(int u, int fa) {for(int e = head[u]; e; e = Next[e]) if(To[e] != fa)dfs2(To[e], u);update(1, n, 1, ord[u], ordr[u], 1);head[u] = 0;return ;}} vt;int main() {n = read();for(int i = 1; i < n; i++) {int a = read(), b = read(), c = read();AddEdge(a, b, c);es[i] = Edge(a, b, c);}build(1, 0);rmq_init();//for(int i = 1; i <= cl; i++) printf("%d%c", Lca[0][i], i < cl ? ‘ ‘ : ‘\n‘);//for(int i = 1; i <= n; i++) printf("%d%c", pos[i], i < n ? ‘ ‘ : ‘\n‘);build(1, n, 1);int q = read();//for(int i = 1; i <= n; i++) printf("%d%c", ord[i], i < n ? ‘ ‘ : ‘\n‘);while(q--) {int cpi = read(); cp = 0;for(int i = 1; i <= cpi; i++) {int e = read(), u = dep[es[e].a] < dep[es[e].b] ? es[e].b : es[e].a;ps[++cp] = psi[i] = u;vis[ps[cp]] = q + 1;flg[ps[cp]] = 1;}if(vis[1] != q + 1) ps[++cp] = 1, flg[1] = 1;sort(psi + 1, psi + cpi + 1, cmp);for(int i = 1; i < cpi; i++) {int c = lca(psi[i], psi[i+1]);if(vis[c] != q + 1) vis[c] = q + 1, ps[++cp] = c;}sort(ps + 1, ps + cp + 1, cmp);//printf("mother_fuck: "); for(int i = 1; i <= cp; i++) printf("%d%c", ps[i], i < cp ? ‘ ‘ : ‘\n‘);vt.init();for(int i = 1; i < cp; i++) {int a = ps[i], b = ps[i+1], c = lca(a, b);vt.AddEdge(b, c, Dep[b] - Dep[c]);}vt.dfs(1, 0);vt.dfs2(1, 0);printf("%lld\n", vt.ans);}return 0;}/*131 2 11 3 12 4 12 5 12 6 13 7 13 8 13 9 17 12 112 13 19 10 110 11 1*/
[hihoCoder#1381]Little Y's Tree