zoukankan      html  css  js  c++  java
  • [湖南集训]谈笑风生

    嘟嘟嘟


    这题刚开始犹豫了一会儿,以为“高明”的优先级大于“谈笑风生”,不过样例表明只要两点间距离不超过(x),两人就算”谈笑风生“。
    接下来看看怎么回答询问。
    首先(a)是固定的,且(a,b)都是(c)的祖先。那就得分类讨论:
    1.(b)(a)的祖先,那么(c)就是(a)的子树中的所有点,根据乘法原理,三元组个数为((size[a] - 1) * min(deep[a], x))
    2.(a)(b)的祖先。那么对于(a)子树内的每一个(b),合法的(c)都有(b)的子树大小个,所以这种情况三元组个数为(sum _ {b in a的子树,dis(a, b) leqslant a} size[b] - 1)。至于怎么求这些合法的(b),显然就是基于(dfs)序的主席树啦。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<assert.h>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 3e5 + 5;
    In ll read()
    {
      ll ans = 0;
      char ch = getchar(), last = ' ';
      while(!isdigit(ch)) last = ch, ch = getchar();
      while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
      if(last == '-') ans = -ans;
      return ans;
    }
    In void write(ll x)
    {
      if(x < 0) x = -x, putchar('-');
      if(x >= 10) write(x / 10);
      putchar(x % 10 + '0');
    }
    In void MYFILE()
    {
    #ifndef mrclr
      freopen(".in", "r", stdin);
      freopen(".out", "w", stdout);
    #endif
    }
    
    int n, m;
    struct Edge
    {
      int nxt, to;
    }e[maxn << 1];
    int head[maxn], ecnt = -1;
    In void addEdge(int x, int y)
    {
      e[++ecnt] = (Edge){head[x], y};
      head[x] = ecnt;
    }
    
    struct Tree
    {
      int ls, rs;
      ll sum;
    }t[maxn * 40];
    int root[maxn], tcnt = 0;
    In void insert(int old, int& now, int l, int r, int val, int d)
    {
      t[now = ++tcnt] = t[old];
      t[now].sum += d;
      if(l == r) return;
      int mid = (l + r) >> 1;
      if(val <= mid) insert(t[old].ls, t[now].ls, l, mid, val, d);
      else insert(t[old].rs, t[now].rs, mid + 1, r, val, d);
    }
    In ll query(int old, int now, int l, int r, int id)
    {
      if(l == r) return t[now].sum - t[old].sum;
      int mid = (l + r) >> 1;
      if(id <= mid) return query(t[old].ls, t[now].ls, l, mid, id);
      else return t[t[now].ls].sum - t[t[old].ls].sum + query(t[old].rs, t[now].rs, mid + 1, r, id);
    }
    
    int dep[maxn], siz[maxn], dfn[maxn], pos[maxn], cnt = 0;
    In void dfs(int now, int _f)
    {
      siz[now] = 1;
      dfn[now] = ++cnt, pos[cnt] = now;
      for(int i = head[now], v; ~i; i = e[i].nxt)
        {
          if((v = e[i].to) == _f) continue;
          dep[v] = dep[now] + 1; 
          dfs(v, now);
          siz[now] += siz[v];
        }
    }
    
    int main()
    {
      MYFILE();
      Mem(head, -1);
      n = read(), m = read();
      for(int i = 1; i < n; ++i)
        {
          int x = read(), y = read();
          addEdge(x, y), addEdge(y, x);
        }
      dfs(1, 0);
      for(int i = 1; i <= cnt; ++i) insert(root[i - 1], root[i], 1, n, dep[pos[i]], siz[pos[i]] - 1);
      for(int i = 1; i <= m; ++i)
        {
          int p = read(), K = read();
          ll ans = 1LL * (siz[p] - 1) * min(dep[p], K);
          ans += query(root[dfn[p]], root[dfn[p] + siz[p] - 1], 1, n, dep[p] + K);
          write(ans), enter;
        }
      return 0;
    }
    
  • 相关阅读:
    Minimum Depth of Binary Tree leetcode java
    Maximum Depth of Binary Tree leetcode java
    Symmetric Tree leetcode java
    Same Tree leetcode java
    Binary Tree Postorder Traversal leetcode java
    Binary Tree Preorder Traversal leetcode java
    Binary Tree Inorder Traversal leetcode java
    Combinations leetcode java
    一键清除Centos iptables 防火墙所有规则
    阿里云centos7.7x64安装open,并配置ip转发和nat伪装
  • 原文地址:https://www.cnblogs.com/mrclr/p/10976227.html
Copyright © 2011-2022 走看看