1 条题解

  • 0
    @ 2023-5-11 22:07:45

    树上前缀和。

    在树上找一条权值和为 s 的链,其中这个链上的点按深度递增(递减)(不同)

    dfs 每搜到一个点求它的前缀和 sum[x],放入 set 中。

    在 set 中找 sum[x] - s 的点,如果有,ans++

    退出 dfs 的时候再把 sum[x] 从 set 中删除

    因为每个点权都是正整数,所以 set 中没有重复元素。

    同时也是单调递增,所以简单些不用 set,开个数组再 lower_bound 也行。

    ——代码

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 100001;
    int n, s, cnt, ans;
    int a[MAXN], head[MAXN], to[MAXN << 1], nxt[MAXN << 1], f[MAXN], sum[MAXN];
    std::set <int> S;
    inline void add(int x, int y)
    {
        to[cnt] = y;
        nxt[cnt] = head[x];
        head[x] = cnt++;
    }
    inline void dfs(int u)
    {
        sum[u] = sum[f[u]] + a[u];
        S.insert(sum[u]);
        if(S.count(sum[u] - s)) ans++;
        for(int i = head[u]; i ^ -1; i = nxt[i]) dfs(to[i]);    
        S.erase(sum[u]);
    }
    int main()
    {
        int i, x, y;
        cin>>n>>s;
        memset(head, -1, sizeof(head));
        for(i = 1; i <= n; i++) cin>>a[i];
        for(i = 1; i < n; i++)
        {
            cin>>x>>y;
            f[y] = x;
            add(x, y);
        }
        S.insert(0);
        dfs(1);
        printf("%d\n", ans);
        return 0;
    }
    
    • 1

    信息

    ID
    63
    时间
    1000ms
    内存
    125MiB
    难度
    3
    标签
    递交数
    131
    已通过
    68
    上传者