zoukankan      html  css  js  c++  java
  • 牛客——求和(dfs序+树状数组)

    原题链接
    题意:
    给定一棵树,有点权;两种操作,一是修改某个单点的权值,二是查询某个点为根节点的子树的点权之和。
    思路:
    dfs序后,子树都处于一个区间里,所以问题就转化成了单点修改、区间求和。
    用树状数组维护即可。
    代码:

    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    const int maxn=1e6+7;
    int n,m,k;
    int h[maxn],idx;
    struct node{
        int e,ne;
    }edge[maxn*2];
    ll w[maxn],tr[maxn*4];
    void add(int u,int v){///前向星存图
        edge[idx]={v,h[u]};h[u]=idx++;
    }
    ll in[maxn],out[maxn],timetmp;
    void dfs(int u,int fa){//dfs记录dfs序列
        in[u]=++timetmp;
        for(int i=h[u];~i;i=edge[i].ne){
            int j=edge[i].e;
            if(j==fa) continue;
            dfs(j,u);
        }
        out[u]=timetmp;
    }
    ///树状数组维护区间
    ll lowbit(int x){
        return x&(-x);
    }
    void update(int pos,int val){
        while(pos<maxn){
            tr[pos]+=val;
            pos=pos+lowbit(pos);
        }
    }
    ll qask(int pos){
        ll res=0;
        while(pos){
            res+=tr[pos];
            pos=pos-lowbit(pos);
        }
        return res;
    }
    int main(){
        cin>>n>>m>>k;
        memset(h,-1,sizeof h);
        for(int i=1;i<=n;i++) cin>>w[i];
        for(int i=1;i<n;i++){
            ll u,v;
            cin>>u>>v;
            add(u,v);add(v,u);
        }
        dfs(k,-1);
        for(int i=1;i<=n;i++)
            update(in[i],w[i]);
        while(m--){
            int op;cin>>op;
            if(op==1){
                ll pos,x;
                cin>>pos>>x;
                update(in[pos],x);
            }
            else{
                int pos;cin>>pos;
                printf("%lld
    ",qask(out[pos])-qask(in[pos]-1));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    01分数规划基本类型
    hdu3976
    hdu1430 康托展开+bfs预处理
    模板
    模板
    redis初始
    mybatis12
    mybatis13
    mybatis10
    springmvc10
  • 原文地址:https://www.cnblogs.com/OvOq/p/14853096.html
Copyright © 2011-2022 走看看