0pts求调

P3806 【模板】点分治 1

luoguljz @ 2024-11-10 14:17:52

#include<bits/stdc++.h>

const int maxN = 20005;
const int maxQ = 105;

using namespace std;

int n, m, hd[maxN], nxt[maxN], to[maxN], val[maxN], cnt_edge;
bool vis[maxN], ans[maxQ];
int max_son[maxN];
int sz[maxN], dis[maxN], query[maxN], node[maxN], tot_node, root;
int question[maxQ];

bool cmp(int x, int y) {
    return dis[x] < dis[y];
}

void add_edge(int u, int v, int w) {
    ++cnt_edge;
    to[cnt_edge] = v;
    val[cnt_edge] = w;
    nxt[cnt_edge] = hd[u];
    hd[u] = cnt_edge;
}

void gen(int x, int fa, int tot) {
    sz[x] = 1;
    max_son[x] = 0;
    for(int i = hd[x]; i; i = nxt[i]) {
        if(vis[to[i]] || to[i] == fa) continue;
        gen(to[i], x, tot);
        sz[x] += sz[to[i]];
        max_son[x] = max(max_son[x], sz[to[i]]);
    }
    max_son[x] = max(max_son[x], tot - sz[x]);
    if(!root || max_son[x] < max_son[root]) root = x;
}

void fdis(int x, int fa, int d, int rt) {
    dis[x] = d;
    query[x] = rt;
    node[++tot_node] = x;
    for(int i = hd[x]; i; i = nxt[i]) {
        if(vis[to[i]] || to[i] == fa) continue;
        fdis(to[i], x, d + val[i], rt);
    }
}

void calc(int x) {
    dis[x] = 0;
    query[x] = x;
    node[1] = x;
    tot_node = 1;
    for(int i = hd[x]; i; i = nxt[x]) {
        if(vis[to[i]]) continue;
        fdis(to[i], x, val[i], to[i]);
    }
    sort(node + 1, node + tot_node + 1, cmp);
    int l, r;
    for(int i = 1; i <= m; ++i) {
        if(ans[i]) continue;
        l = 1, r = tot_node;
        while(l < r) {
            if(dis[node[l]] + dis[node[r]] > question[i]) {
                --r;
            }
            else if(dis[node[l]] + dis[node[r]] < question[i]) {
                ++l;
            }
            else if(query[node[l]] == query[node[r]]) {
                if(dis[node[r - 1]] == dis[node[r]]) --r;
                else ++l;
            }
            else {
                ans[i] = true;
                break;
            }
        }
    }
}

void build(int x) {
    calc(x);
    vis[x] = true;
    for(int i = hd[x]; i; i = nxt[i]) {
        if(vis[to[i]]) continue;
        root = 0;
        gen(to[i], 0, sz[to[i]]);
        build(root);
    }
}

int main() {
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n - 1; ++i) {
        int u, v, w;
        scanf("%d %d %d", &u, &v, &w);
        add_edge(u, v, w);
        add_edge(v, u, w);
    }
    for(int i = 1; i <= m; ++i) {
        scanf("%d", &question[i]);
        if(!question[i]) ans[i] = true;
    }
    max_son[0] = n;
    gen(1, 0, n);
    build(root);
    for(int i = 1; i <= m; ++i) {
        printf((ans[i] ? "AYE\n" : "NAY\n"));
    }
    return 0;
}

|