• P3899 [湖南集训]谈笑风生


    P3899 [湖南集训]谈笑风生
    这题定义诡异,似乎对于一对 (x, y) 如果 (y)(x) 在范围 (k) 以内的儿子,那么 (x) 既和它彼此彼此,又高明到不知道哪里去了
    然后你思考一下,分两部分:

    1. (x)(y) 的祖先。
    2. (y)(x) 的祖先。

    容易发现,当你在 (x) 的时候.
    第一部分 (sum_1 = min(dep_x - 1, k) cdot (siz_x-1))

    第二部分 (sum_2 = displaystyle sum_{v in subtree_u & dep_v - dep_u le k} siz_v)

    第二部分显然很线段树合并,第一部分 (O(1)) 算。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    
    using namespace std;
    
    typedef long long ll;
    const ll MAXN = 3e5+10;
    
    struct que {
        ll k, id;
        que(){}
        que(ll _k, ll _id){k = _k, id = _id;}
    };
    
    struct nod {
        ll l, r, val;
    } t[MAXN * 30];
    
    ll N, M, ans[MAXN], siz[MAXN], rt[MAXN], tot;
    vector <ll> g[MAXN];
    vector <que> q[MAXN];
    
    ll ask(ll, ll, ll, ll, ll);
    void dfs(ll, ll);
    void dfs2(ll, ll, ll);
    void ins(ll&, ll, ll, ll, ll);
    ll mer(ll, ll);
    
    int main() {
        scanf("%lld%lld", &N, &M);
        for (ll i = 1, x, y; i < N; i++) {
            scanf("%lld%lld", &x, &y);
            g[x].push_back(y);
            g[y].push_back(x);
        }
        for (ll i = 1, p, k; i <= M; i++) {
            scanf("%lld%lld", &p, &k);
            q[p].push_back(que(k, i));
        }
        dfs(1, 0);
        dfs2(1, 0, 1);
        for (ll i = 1; i <= M; i++)
        	printf("%lld
    ", ans[i]);
        return 0;
    }
    
    void dfs(ll n, ll ff) {
        siz[n] = 1;
        for (unsigned int i = 0 ; i < g[n].size(); i++) {
            ll v = g[n][i];
            if (v == ff) continue;
            dfs(v, n);
            siz[n] += siz[v];
        }
    }
    
    void dfs2(ll n, ll ff, ll dep) {
        ins(rt[n], 1, N, dep, siz[n]-1);
        for (unsigned int i = 0; i < g[n].size(); i++) {
            ll v = g[n][i];
            if (v == ff) continue;
            dfs2(v, n, dep+1);
            rt[n] = mer(rt[n], rt[v]);
        }
        for (unsigned int i = 0; i < q[n].size(); i++) {
            ans[q[n][i].id] = min(q[n][i].k, dep-1) * (siz[n]-1) + ask(rt[n], 1, N, dep+1, dep+q[n][i].k);
        }
    }
    
    void ins(ll &node, ll l, ll r, ll pos, ll val) {
        if (!node) node = ++tot;
        t[node].val += val;
        if (l == pos && pos == r) return;
        ll mid = (l + r) >> 1;
        if (pos <= mid) ins(t[node].l, l, mid, pos, val);
        else ins(t[node].r, mid+1, r, pos, val);
    }
    
    ll ask(ll node, ll l, ll r, ll a, ll b) {
        if (!node) return 0;
        if (a <= l && r <= b) return t[node].val;
        ll mid = (l + r) >> 1, ret = 0;
        if (a <= mid) ret += ask(t[node].l, l, mid, a, b);
        if (mid < b) ret += ask(t[node].r, mid+1, r, a, b);
        return ret;
    }
    
    ll mer(ll x, ll y) {
        if (!x || !y) return x | y;
        t[x].val += t[y].val;
        t[x].l = mer(t[x].l, t[y].l);
        t[x].r = mer(t[x].r, t[y].r);
        return x;
    }
    
  • 相关阅读:
    pycharm 安装第三方库报错:AttributeError: 'module' object has no attribute 'main'
    CentOS7.x 设置显示vi/vim行号
    centos下使用yum 安装pip
    kubelet服务启动失败,错误代码255
    服务器时间设置
    解决umount.nfs: /data: device is busy 问题
    vim修改权限: E45: 已设定选项 'readonly' (请加 ! 强制执行)
    Postgresql 截取字符串
    《算法竞赛进阶指南》0x31质数 阶乘分解质因数
    《算法竞赛进阶指南》0x31质数 POJ2689 Prime Distance
  • 原文地址:https://www.cnblogs.com/Gensokyo-Alice/p/13913338.html
Copyright © 2020-2023  润新知