• 树的距离


    树的距离

    题目大意:wyf非常喜欢树。一棵有根数树上有N个节点,1号点是他的根,每条边都有一个距离,而wyf是个爱问奇怪问题的熊孩子,他想知道对于某个点x,以x为根的子树上,所有与x距离大于等于k的点与x的距离之和。N<=2e5

    思路:可以考虑离线算法,我们先将树dfs一遍,我们按dfs序在w中保存各个节点的深度的和序号,L[x],R[x],dis[x]分别表示以x为根的子树对应的dfs序的左右端点,以及x的深度。对每个操作q我们记录子树根节点,和v值,v=dis[x]+k。然后我们将w按节点深度从大到小排序,q按v值从大到小排序。开两个树状数组,第一个记录已经加入的节点的个数的前缀和,另一个记录已加入节点的深度的前缀和。 遍历操作q,将比q.v大或相等的节点的加入到两个树状数组中,我们再查询以q.x对应的dfs序的左右端点之间一共有多少个点cnt,和这些点的深度和是多少sum,那么这次操作的答案就是sum-cnt*dis[q.x]。

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 const int N=2*1e5+5;
     5 int n,m,head[N],tot,top,L[N],R[N];
     6 ll bit[2][N],dis[N],ans[N];
     7 struct edge
     8 {
     9     int f,t,next; ll v;
    10 }e[N];
    11 struct node
    12 {
    13     int id; ll v;
    14     bool operator <(const node &rhs)const
    15     {
    16         return v>rhs.v;
    17     }
    18 }w[N];
    19 struct query
    20 {
    21     int id,x; ll v;
    22     bool operator <(const query &rhs)const
    23     {
    24         return v>rhs.v;
    25     }
    26 }q[N];
    27 void add(int f,int t,ll v)
    28 {
    29     e[tot].f=f; e[tot].t=t; e[tot].v=v;
    30     e[tot].next=head[f]; head[f]=tot++;
    31 }
    32 void update(int x,ll v,int op)
    33 {
    34     while(x<N)
    35     {
    36         bit[op][x]+=v;
    37         x+=x&(-x);
    38     }
    39 }
    40 ll query(int x,int op)
    41 {
    42     ll ans=0;
    43     while(x>0)
    44     {
    45         ans+=bit[op][x];
    46         x-=x&(-x);
    47     }
    48     return ans;
    49 }
    50 void dfs(int v,int p,ll d)
    51 {
    52     dis[v]=d;
    53     L[v]=++top;
    54     w[top].v=d; w[top].id=top;
    55     for(int i=head[v];~i;i=e[i].next)
    56     {
    57         int nx=e[i].t;
    58         if(dis[nx]) continue;
    59         dfs(nx,v,d+e[i].v);
    60     }
    61     R[v]=top;
    62 }
    63 int main()
    64 {
    65     memset(head,-1,sizeof(head)); tot=top=0;
    66     scanf("%d",&n);
    67     for(int i=2;i<=n;i++)
    68     {
    69         int P; ll D;
    70         scanf("%d%lld",&P,&D);
    71         add(P,i,D);
    72     }
    73     dfs(1,0,1);
    74     scanf("%d",&m);
    75     for(int i=1;i<=m;i++)
    76     {
    77         int x; ll k; scanf("%d%lld",&x,&k);
    78         q[i].x=x; q[i].v=dis[x]+k;
    79         q[i].id=i;
    80     }
    81     sort(w+1,w+1+n);
    82     sort(q+1,q+1+m);
    83     int j=1;
    84     for(int i=1;i<=m;i++)
    85     {
    86         for(;w[j].v>=q[i].v && j<=n;j++)
    87         {
    88             update(w[j].id,1,0);
    89             update(w[j].id,w[j].v,1);
    90         }
    91         ll cnt=query(R[q[i].x],0)-query(L[q[i].x]-1,0);
    92         ll sum=query(R[q[i].x],1)-query(L[q[i].x]-1,1);
    93         ans[q[i].id]=sum-cnt*dis[q[i].x];
    94     }
    95     for(int i=1;i<=m;i++) printf("%lld
    ",ans[i]);
    96     return 0;
    97 }
    View Code
  • 相关阅读:
    洞察僵尸网络的4条关键线索,你知道吗?
    数据即服务(DaaS)的好处和趋势
    AIOT:什么是智联网,它是未来吗?
    渐变略过效果
    页面头部banner动画效果
    小三角
    监测屏幕宽度
    开关效果
    高级轮播
    手机端跳转页面指定楼层
  • 原文地址:https://www.cnblogs.com/CJLHY/p/7895286.html
Copyright © 2020-2023  润新知