洛谷【P3806】点分治

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 5;
const int maxk = 1e7 + 5;
vector<pair<int, int> >edge[maxn];
///n点m询问,rt->当前重心,sum->当前树大小,cnt->计数器
int n, m, rt, sum, cnt;
///tmp->记录算出的距离,siz->记录子树大小,dis[i]->为rt与i之间的距离
///maxp->用于找重心,q->用于记录所有询问
int tmp[maxn], siz[maxn], dis[maxn], maxp[maxn], q[105];
///judge[i]->记录在之前子树中距离i是否存在,ans->记录第k个询问是否存在,vis->记录被删除的结点
bool judge[maxk], ans[105], vis[maxn];

inline int read(){
    int s = 0, w = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') w = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
    return s * w;
}

inline void print(int x){
    if(x < 0) x = ~x + 1, putchar('-');
    if(x > 9) print(x / 10);
    putchar(x % 10 + '0');
}

void dfs(int u, int f){///找重心
    siz[u] = 1, maxp[u] = 0;
    for(int i = 0; i < edge[u].size(); i++){
        int v = edge[u][i].first;
        if(v == f || vis[v]) continue;
        dfs(v, u);
        siz[u] += siz[v];
        if(siz[v] > maxp[u]) maxp[u] = siz[v];
    }
    maxp[u] = max(maxp[u], sum - siz[u]);
    if(maxp[u] < maxp[rt]) rt = u;
}

void dfs1(int u, int f){///统计当前子树的所有节点到根节点的距离
    tmp[cnt++] = dis[u];
    for(int i = 0; i < edge[u].size(); i++){
        int v = edge[u][i].first;
        if(v == f || vis[v]) continue;
        dis[v] = dis[u] + edge[u][i].second;
        dfs1(v, u);
    }
}

void solve(int u){///更新答案
    queue<int>Q;
    for(int i = 0; i < edge[u].size(); i++){
        int v = edge[u][i].first;
        if(vis[v]) continue;
        cnt = 0;
        dis[v] = edge[u][i].second;
        dfs1(v, u);
        for(int j = 0; j < cnt; j++)
            for(int k = 0; k < m; k++)
                if(q[k] >= tmp[j])
                    ans[k] |= judge[q[k] - tmp[j]];
        for(int j = 0; j < cnt; j++)
            if(tmp[j] < maxk) judge[tmp[j]] = true, Q.push(tmp[j]);
    }
    while(!Q.empty())
        judge[Q.front()] = false, Q.pop();
}

void divide(int u){///点分治
    vis[u] = judge[0] = true;
    solve(u);
    for(int i = 0; i < edge[u].size(); i++){
        int v = edge[u][i].first;
        if(vis[v]) continue;
        maxp[rt = 0] = sum = siz[v];
        dfs(v, 0);
        dfs(rt, 0);
        divide(rt);
    }
}

int main(){
    n = read(), m = read();
    for(int i = 1; i < n; i++){
        int u = read(), v = read(), w = read();
        edge[u].push_back(make_pair(v, w));
        edge[v].push_back(make_pair(u, w));
    }
    for(int i = 0; i < m; i++) q[i] = read();
    maxp[0] = sum = n;
    dfs(1, 0);
    dfs(rt, 0);
    divide(rt);
    for(int i = 0; i < m; i++){
        if(ans[i]) puts("AYE");
        else puts("NAY");
    }

    return 0;
}
/*
* ┌───┐   ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐
* │Esc│   │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│  ┌┐    ┌┐    ┌┐
* └───┘   └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘  └┘    └┘    └┘
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐
* │~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│& 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │Num│ / │ * │ - │
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤
* │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{ [│} ]│ | \ │ │Del│End│PDn│ │ 7 │ 8 │ 9 │   │
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ + │
* │ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter  │               │ 4 │ 5 │ 6 │   │
* ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤     ┌───┐     ├───┼───┼───┼───┤
* │ Shift  │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│  Shift   │     │ ↑ │     │ 1 │ 2 │ 3 │   │
* ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││
* │ Ctrl│ Win│ Alt│         Space         │ Alt│ Win│Menu│Ctrl│ │ ← │ ↓ │ → │ │   0   │ . │←─┘│
* └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘
*/

全部评论

相关推荐

985柜员:开发还敢还叫,全部让自测就老实了
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
正在热议
更多
# 春招至今,你的战绩如何? #
10999次浏览 94人参与
# 你的实习产出是真实的还是包装的? #
1943次浏览 42人参与
# MiniMax求职进展汇总 #
24114次浏览 309人参与
# 军工所铁饭碗 vs 互联网高薪资,你会选谁 #
7628次浏览 43人参与
# 简历第一个项目做什么 #
31736次浏览 339人参与
# 重来一次,我还会选择这个专业吗 #
433536次浏览 3926人参与
# 米连集团26产品管培生项目 #
6027次浏览 216人参与
# 当下环境,你会继续卷互联网,还是看其他行业机会 #
187191次浏览 1122人参与
# 牛客AI文生图 #
21445次浏览 238人参与
# 不考虑薪资和职业,你最想做什么工作呢? #
152441次浏览 888人参与
# 研究所笔面经互助 #
118960次浏览 577人参与
# 简历中的项目经历要怎么写? #
310349次浏览 4217人参与
# AI时代,哪些岗位最容易被淘汰 #
63803次浏览 826人参与
# 面试紧张时你会有什么表现? #
30509次浏览 188人参与
# 你今年的平均薪资是多少? #
213128次浏览 1039人参与
# 你怎么看待AI面试 #
180122次浏览 1258人参与
# 高学历就一定能找到好工作吗? #
64331次浏览 620人参与
# 你最满意的offer薪资是哪家公司? #
76537次浏览 374人参与
# 我的求职精神状态 #
448121次浏览 3129人参与
# 正在春招的你,也参与了去年秋招吗? #
363503次浏览 2638人参与
# 腾讯音乐求职进展汇总 #
160672次浏览 1112人参与
# 校招笔试 #
471140次浏览 2964人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务