zoukankan      html  css  js  c++  java
  • ACM-ICPC 2018 沈阳赛区网络预赛 J. Ka Chang(树状数组+分块)

    Given a rooted tree ( the root is node 1 ) of N nodes. Initially, each node has zero point.

    Then, you need to handle Q operations. There're two types:

    1 L X: Increase points by X of all nodes whose depth equals L ( the depth of the root is zero ). (x≤108)

    2 X: Output sum of all points in the subtree whose root is X.

    Input
    Just one case.

    The first lines contain two integer, N,Q(N≤105,Q≤105).

    The next n−1 lines: Each line has two integer aaa,bbb, means that node aaa is the father of node b. It's guaranteed that the input data forms a rooted tree and node 1 is the root of it.

    The next Q lines are queries.

    Output
    For each query 2, you should output a number means answer.

    样例输入
    3 3
    1 2
    2 3
    1 1 1
    2 1
    2 3

    样例输出
    1
    0

    题意

    给你一颗以1为根节点的数,有两个操作

    1.层数为L的节点增加X

    2.查询以X为根节点的子树总权和

    题解

    操作2很容易想到dfs维护树状数组

    对于操作1,可以把层数按sqrt(n)分块,对于层数点数<=block的直接暴力更新,对于>block先保存进数组ans,查询的时候二分左右区间可以知道根的节点数,再乘ans,这样可以把单次操作的复杂度固定在sqrt(n)范围内

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define LL long long
     5 
     6 const int maxn=1e5+5;
     7 int s[maxn],e[maxn],tot,n;
     8 LL sum[maxn],ans[maxn];
     9 vector<int>G[maxn],deep[maxn],q;
    10 void dfs(int u,int fa,int d)
    11 {
    12     s[u]=++tot;
    13     deep[d].push_back(s[u]);
    14     for(auto v:G[u])
    15     {
    16         if(v==fa)continue;
    17         dfs(v,u,d+1);
    18     }
    19     e[u]=tot;
    20 }
    21 int lowbit(int x)
    22 {
    23     return x&(-x);
    24 }
    25 void update(int x,int add)
    26 {
    27     for(int i=x;i<=n;i+=lowbit(i))
    28         sum[i]+=add;
    29 }
    30 LL query(int x)
    31 {
    32     LL ans=0;
    33     for(int i=x;i>0;i-=lowbit(i))
    34         ans+=sum[i];
    35     return ans;
    36 }
    37 int main()
    38 {
    39     int Q,op,L,x,u,v;
    40     scanf("%d%d",&n,&Q);
    41     int block=sqrt(n);
    42     for(int i=1;i<n;i++)
    43     {
    44         scanf("%d%d",&u,&v);
    45         G[u].push_back(v);
    46         G[v].push_back(u);
    47     }
    48     dfs(1,-1,0);
    49     for(int i=0;i<n;i++)
    50         if(deep[i].size()>block)q.push_back(i);
    51     for(int i=0;i<Q;i++)
    52     {
    53         scanf("%d",&op);
    54         if(op==1)
    55         {
    56             scanf("%d%d",&L,&x);
    57             if(deep[L].size()>block)ans[L]+=x;
    58             else
    59             {
    60                 for(auto X:deep[L])
    61                     update(X,x);
    62             }
    63         }
    64         else
    65         {
    66             scanf("%d",&x);
    67             LL res=query(e[x])-query(s[x]-1);
    68             for(auto pos:q)
    69                 res+=ans[pos]*(upper_bound(deep[pos].begin(),deep[pos].end(),e[x])-lower_bound(deep[pos].begin(),deep[pos].end(),s[x]));
    70             printf("%lld
    ",res);
    71         }
    72     }
    73     return 0;
    74 }
  • 相关阅读:
    Java n个线程轮流打印数字的问题
    【我所认知的BIOS】—&gt; uEFI AHCI Driver(6) AtaAtapiPassThruSupported的局部变量们
    设备树学习之(二)点灯【转】
    设备树学习之(一)GPIO中断【转】
    S5PV210开发板 VGA测试【转】
    Linux VGA驱动移植实验【转】
    略过天涯 深入浅出VGA和DVI接口【转】
    基于FPGA的VGA可移植模块终极设计【转】
    字符串函数---strcmp()与strncmp()详解及实现【转】
    关于内存中栈和堆的区别(非数据结构中的堆和栈,区别)
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/9649951.html
Copyright © 2011-2022 走看看