zoukankan      html  css  js  c++  java
  • gym 100589A queries on the Tree 树状数组 + 分块

    题目传送门

    题目大意:

      给定一颗根节点为1的树,有两种操作,第一种操作是将与根节点距离为L的节点权值全部加上val,第二个操作是查询以x为根节点的子树的权重。

    思路:

      思考后发现,以dfs序建立树状数组,方便查询,不方便修改,以bfs序建立树状数组,方便修改,不方便查询。

      在计算子树权重的时候发现,如果我能算出 所有层 属于这棵子树的  点数*对应层需要加上的val,那么就得到了这棵树的总权重。但是显然暴力统计点数会超时,于是我们把用一个分块的想法,对于一层来说,如果这层的总点数小于块的大小,就暴力树状数组修改,如果大于快,就用一个数组记录一下修改的值,并且把这一层保存到一个large的vector里面,表示这些层我是没有计算到树状数组里的。

      在查询的时候,先用dfs序弄出每一个节点的(l,r)区间,统计树状数组里的值,然后对large里面的层来说,由于我实现记录好了每个层节点的dfs序号,并且是按照从小打到的顺序的,对于每个large层来说,只要是大于等于序号 l ,小于等于序号 r 的节点都属于这个点,所以用upper_bound和lower_bound来计算就得到了点数,乘以每一层对应的val就可以了。

    #include<cstdio>
    #include<cstring>
    #include<stdlib.h>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<map>
    #include<queue>
    #include<vector>
    #define CLR(a,b) memset(a,b,sizeof(a))
    #define PI acos(-1)
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const int maxn=100010;
    struct edge{
        int to,Next;
    }e[maxn];
    int n,m;
    int tot,head[maxn],u,v,L[maxn],R[maxn],time,dfn[maxn];
    ll val[maxn];
    int limit;
    ll c[maxn];
    inline int lowbit(int x){
        return x&(-x);
    }
    inline void add(int x,ll val){
        while(x<=n){
            c[x]+=val;
            x+=lowbit(x);
        }
    }
    inline ll getsum(int x){
        ll ans=0;
        while(x>0)
        {
            ans+=c[x];
            x-=lowbit(x);
        }
        return ans;
    }
    vector<int >large;//大的层 
    vector<int >pos[maxn];//每一层有哪些点 
    inline void init(){
        CLR(head,-1),tot=0,time=0;
        large.clear();
        CLR(c,0),CLR(val,0);
        for(int i=0;i<=n;i++){
            pos[i].clear();
        }
        limit=1000;
    
    }
    inline void addv(int u,int v){
        e[++tot]={v,head[u]};
        head[u]=tot;
    }
    
    inline void dfs(int u,int deep){
        dfn[u]=++time;
        pos[deep].push_back(time);
        L[u]=time;
        for(int i=head[u];i!=-1;i=e[i].Next)
        {
            int v=e[i].to;
            dfs(v,deep+1);
        }
        R[u]=time;
    }
    int main(){
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            init();
            for(int i=1;i<n;i++)
            {
                scanf("%d%d",&u,&v);
                addv(u,v);
            }
            dfs(1,0);
            for(int i=0;i<=n;i++)
            {
                if(pos[i].size()>limit)
                {
                    large.push_back(i);
                }
            }
            int dis,x,op;
            ll y;
            while(m--)
            {
                scanf("%d",&op);
                if(op==1)
                {
                    scanf("%d%lld",&dis,&y);
                    if(pos[dis].size()<=limit)
                    {
                        for(int i=0;i<pos[dis].size();i++)
                        {
                            add(pos[dis][i],y);
                        }
                    }
                    else{
                        val[dis]+=y;
                    }
                }else{
                    scanf("%d",&x);
                //    printf("l:%d  r:%d
    ",L[x],R[x]);
                    ll ans=getsum(R[x])-getsum(L[x]-1);
                    for(int i=0;i<large.size();i++)
                    {
                        ans+=val[large[i]]*(upper_bound(pos[large[i]].begin(),pos[large[i]].end(),R[x])-lower_bound(pos[large[i]].begin(),pos[large[i]].end(),L[x]));
                    }
                    printf("%lld
    ",ans);
                }
            }
            
        }
    }
    
    /*
    1 6
    1 0 1
    2 1
    1 0 3
    2 1
    1 0 1
    1 0 1
    */
    A. Queries on the Tree
    time limit per test
    2.0 s
    memory limit per test
    512 MB
    input
    standard input
    output
    standard output

    You are given a directed tree with N with nodes numbered 1 to N and rooted at node 1. Each node initially contains 0 coins.

    You have to handle a total of M operations:

    • L Y : Increase by Y the coins of all nodes which are at a distance L from root.
    • X : Report the sum of coins of all nodes in subtree rooted at node X.
    Input

    First line contains N and M. Each of the next N - 1 lines contains u and v denoting directed edge from node numbered u to v.

    Each of the next M lines contain queries of either Type 1 or 2.

    Output

    For each query of Type 2, print the required sum.

    Constraints

    • 1 ≤ N ≤ 105
    • 1 ≤ M ≤ 104
    • 0 ≤ L ≤ Maximum height of tree
    • 0 ≤ Y ≤ 109
    • 1 ≤ Xuv ≤ N
    Examples
    input
    Copy
    5 4
    1 2
    1 3
    3 4
    3 5
    1 1 2
    1 2 3
    2 3
    2 1
    output
    Copy
    8
    10
    Note

    In first update nodes 2 and 3 are increased by 2 coins each.

    In second update nodes 4 and 5 are increased by 3 each.

  • 相关阅读:
    别再为了this发愁了:JS中的this机制
    专为控制打印设计的CSS样式
    怎样用纯HTML和CSS更改默认的上传文件按钮样式
    将HTML转成XHTML并清除一些无用的标签和属性
    JavaScript中textRange对象使用方法总结
    DIV+CSS规范命名集合
    JS条件判断
    CSS只是进化的一部分
    25 个超棒的 HTML5 & JavaScript 游戏引擎开发库
    开发一个完整的JavaScript组件
  • 原文地址:https://www.cnblogs.com/mountaink/p/9867052.html
Copyright © 2011-2022 走看看