題解 HNOI2014 世界樹

2022-05-07 23:06:25 字數 1941 閱讀 6762

[hnoi2014]世界樹

從資料範圍很容易看出是個虛樹dp(可惜看出來了也還是不會做)

虛樹大家應該都會, 不會的話自己去搜吧, 我懶得講了, 我們在這裡只需要考慮如何dp即可

首先我們需要求出每個點被哪個點所控制, 設\(u\)點被\(bl[u]\)所控制, 兩遍dfs即可, 考慮兒子對父親的影響和父親對兒子的影響

**細節相信不要我說, 能做這道題的總不可能不會dfs吧

還是貼一下自己看吧

void dfs1(int u, int fa)

}void dfs2(int u, int fa)

}//分別在遞迴前和遞迴後處理一下就完事了

然後考慮如何計算答案, 對虛樹上每一條邊討論

①: 邊的兩端被同乙個節點所控制, 加上這兩個點不在虛樹中的兒子的sz即可

②: 邊的兩端被不同點控制, 我們需要找出乙個分界點, 滿足此分界點歸下面那個點的\(bl\)所控制, 此分界點的父親被上面那個點的\(bl\)所控制, 用個資料結構維護一下或者倍增跳一下就可以了

至於每個點不在虛樹中的兒子的sz, 拿當前點的sz減去所有他在虛樹中的兒子的sz即可

具體實現細節參見**(參考了一下題解的思路嘿嘿嘿)

#include #include #include #include #define n 300005

using namespace std;

int n, m, q, head[n], sz[n], son[n], dep[n], dfn[n], f[n][21], top[n], cnt, tp, a[n], b[n], stk[n], bl[n], con[n], ans[n], l[n];

struct edge e[n << 1];

inline int read()

while(c >= '0' && c <= '9')

return x * w;

}inline void add(int u, int v) ; head[u] = cnt; }

void dfs_sz(int u, int fa)

}void dfs_top(int x, int y)

int lca(int x, int y)

return dep[x] < dep[y] ? x : y;

}bool cmp(int x, int y)

void dfs1(int u, int fa)

}int dis(int x, int y)

void dfs2(int u, int fa)

}void dp(int u)

for(int j = l[dep[v]]; j >= 0; j--)

ans[bl[u]] += sz[s] - sz[mid];

ans[bl[v]] += sz[mid] - sz[v];

} ans[bl[u]] += con[u];

}void query()

dfs1(1, 0); dfs2(1, 0); dp(1);

for(int i = 1; i <= m; i++) printf("%d%c", ans[b[i]], i == m ? '\n' : ' ');

for(int i = 1; i <= len; i++) bl[a[i]] = ans[a[i]] = con[a[i]] = 0;

}int main()

cnt = 0; dfs_sz(1, 0); dfs_top(1, 0);

for(int i = 1; i <= n; i++)

for(int j = 1; j <= 20; j++)

f[i][j] = f[f[i][j - 1]][j - 1];

q = read(); while(q--) query();

return 0;

}

題解 HNOI 2014 世界樹

洛谷 bzoj loj 題目概要 給定一棵 n n 個節點的樹,q role presentation q q次詢問 給定 m m 個關鍵點,每個原樹上的點被最近且序號最小的關鍵點控制,問每個關鍵點 n,q,m 300000 role presentation n,q m 300000n,q,m 3...

P3233 HNOI2014 世界樹(虛樹)

看到 mi 300000自然聯想到虛樹,簡單思考一下似乎可行,但剩下的部分貌似就比較麻煩。首先對重新構建的虛樹,考慮每個點應該被誰管。因為乙個點既可以被它子樹中的點管,也可以被子樹以外的點管,所以我們做兩次dfs。第一次先遍歷子節點,再更新,記錄的是乙個點子樹中最近的管他的點是誰。第二次先用從父節點...

虛數 BZOJ3572 HNOI2014 世界樹

給出一顆樹,每次選中m個點,對於樹上任意乙個點,會被其最近的乙個選中點包含 相同有編號小優先 求每個選中點包含了多少個點。之前寫過兩次都沒寫部落格。結果複習板題的時候,連題意都不知道。方法就是虛數板子 include include include include define sf scanf d...