zoukankan      html  css  js  c++  java
  • 3653: 谈笑风生

    3653: 谈笑风生 

    链接

    分析:

      $ans = min(deep[x] - 1, k) * siz[x] - 1 +sumlimits_{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
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    tensorflow 镜像
    TDD、BDD、DDD
    Node.js结合Selenium做Web自动化测试
    Selenium 对元素element的操作举例
    Selenium UI 举例 getCssValue
    《测之重器——自动化测试框架搭建指南》
    《Robot Framework自动化测试修炼宝典》道长
    SQLServer中round函数
    SQLServer中对时间和长度的处理
    SQLServer中获取所有数据库名、所有表名、所有字段名的SQL语句
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10288346.html
Copyright © 2011-2022 走看看