P3806 模板点分治1
Posted oi-forever
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3806 模板点分治1相关的知识,希望对你有一定的参考价值。
题意:给定一棵有n个点的树,询问树上距离为k的点对是否存在。
总结:点分查询的时候,距离<=k - 1 && <= k的路径即为距离为k的点对
#include<bits/stdc++.h> using namespace std; const int maxn = 20005; int head[maxn], cnt = 1, n, m, d[maxn], siz[maxn], f[maxn], vis[maxn]; struct Node{ int v, nxt, w; } G[maxn]; int root, ans, can[maxn], tot, dep[maxn]; void ins(int u, int v, int w) { G[cnt] = (Node) {v, head[u], w}; head[u] = cnt++; } int q[maxn]; void get_rt(int x, int fa) { siz[x] = 1; f[x] = 0; for (int i = head[x]; i; i = G[i].nxt) { int v = G[i].v; if(vis[v] || v == fa) continue; get_rt(v, x); siz[x] += siz[v]; f[x] = max(f[x], siz[v]); } f[x] = max(f[x], ans - siz[x]); if(f[x] < f[root]) root = x; } void get_dp(int x, int fa) { d[++tot] = dep[x]; for (int i = head[x]; i; i = G[i].nxt) { int v = G[i].v; if(vis[v] || v == fa) continue; dep[v] = dep[x] + G[i].w; get_dp(v, x); } } void calc(int x, int w, int sig) { tot = 0; dep[x] = w; get_dp(x, 0); sort(d + 1, d + tot + 1); for (int i = 1; i <= m; ++i) { int l = 1, r = tot, res1 = 0, res2 = 0; while(l < r) { if(d[l] + d[r] <= q[i]) res1 += (r - l), l++; else r--; } l = 1, r = tot; while(l < r) { if(d[l] + d[r] <= q[i] - 1) res2 += (r - l), l++; else r--; } can[i] += (res1 - res2) * sig; } } void work(int x) { calc(x, 0, 1); vis[x] = 1; for (int i = head[x]; i; i = G[i].nxt) { int v = G[i].v; if(vis[v]) continue; calc(v, G[i].w, -1); ans = siz[v]; root = 0; get_rt(v, 0); work(root); } } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n - 1; ++i) { int x, y, z; scanf("%d%d%d", &x, &y, &z); ins(x, y, z); ins(y, x, z); } for (int i = 1; i <= m; ++i) scanf("%d", &q[i]); root = 0, ans = n; f[0] = 0x7fffff; get_rt(1, 0); work(root); for (int i = 1; i <= m; ++i) { can[i] > 0 ?printf("AYE\n") :printf("NAY\n"); } return 0; }
以上是关于P3806 模板点分治1的主要内容,如果未能解决你的问题,请参考以下文章