码迷,mamicode.com
首页 > 其他好文 > 详细

3653: 谈笑风生

时间:2019-01-18 17:28:00      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:include   getch   time   str   部分   ios   ++   namespace   stream   

3653: 谈笑风生 

链接

分析:

  $ans = min(deep[x] - 1, k) * siz[x] - 1 +\sum\limits_{y是u子树内的点}(siz[y] - 1)$

  前面的可以$O(1)$算,后面的那一部分可以dfs序+主席树维护。

  或者dfs的过程中+线段树合并。或者长链剖分。

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;

inline int read() {
    int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch==-)f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-0;return x*f;
}

const int N = 600005;
struct Edge{ int to, nxt; } e[N << 1];
int head[N], deep[N], fa[N], siz[N], st[N], ed[N], tr[N], En, Index, TimeIndex;
int ls[N * 20], rs[N * 20], Root[N];
LL sum[N * 20];

inline void add_edge(int u,int v) {
    ++En; e[En].to = v, e[En].nxt = head[u]; head[u] = En;
    ++En; e[En].to = u, e[En].nxt = head[v]; head[v] = En;
}
void dfs(int u) {
    deep[u] = deep[fa[u]] + 1;
    siz[u] = 1;
    st[u] = ++TimeIndex;tr[TimeIndex] = u;
    for (int i = head[u]; i; i = e[i].nxt) {
        int v = e[i].to;
        if (v == fa[u]) continue;
        fa[v] = u;
        dfs(v);
        siz[u] += siz[v];
    }
    ed[u] = TimeIndex;
}
void update(int l,int r,int last,int &now,int p) {
    if (!now) now = ++Index;
    sum[now] += sum[last] + siz[tr[p]] - 1; /// !!!
    if (l == r) return ;
    int mid = (l + r) >> 1;
    if (deep[tr[p]] <= mid) {
        rs[now] = rs[last];
        update(l, mid, ls[last], ls[now], p);
    } else {
        ls[now] = ls[last];
        update(mid + 1, r, rs[last], rs[now], p);
    }
}
LL query(int l,int r,int last,int now,int L,int R) {
    if (L <= l && r <= R) return sum[now] - sum[last];
    int mid = (l + r) >> 1; LL res = 0;
    if (L <= mid) res = query(l, mid, ls[last], ls[now], L, R);
    if (R > mid) res += query(mid + 1, r, rs[last], rs[now], L, R);
    return res;
}
int main() {
    int n = read(), Q = read(), D;
    for (int i = 1; i < n; ++i) {
        int u = read(), v = read();
        add_edge(u, v);
    }
    dfs(1);
    for (int i = 1; i <= n; ++i) D = max(D, deep[i]);
    for (int i = 1; i <= n; ++i) {
        update(1, D, Root[i - 1], Root[i], i);
    }
    LL ans = 0;
    while (Q--) {
        int x = read(), k = read();
        ans = 1ll * min(deep[x] - 1, k) * (siz[x] - 1);
        if (deep[x] < D) ans += query(1, D, Root[st[x]], Root[ed[x]], deep[x] + 1, min(D, deep[x] + k));
        printf("%lld\n", ans);
    }
    return 0;
}

 

3653: 谈笑风生

标签:include   getch   time   str   部分   ios   ++   namespace   stream   

原文地址:https://www.cnblogs.com/mjtcn/p/10288346.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!