zoukankan      html  css  js  c++  java
  • hdu3966-树刨+bit区间修改单点查询

    题意:对树上两点区间增加或减少每点的权值,单点查询每点的权值。
    思路:一开始线段树写的,但是我的被卡了2*maxn的空间,优化一下就可以了,但是嫌太麻烦,出题人可能就打算卡部分人的线段树。
    用bit的话,类似预处理数组,每次查询0-x点的区间和就可以,修改左端点和右端点的权值为v和-v即可。
    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    const int maxn = 5e4+5;
    int n,m,id,q,top[maxn],a[maxn],p[maxn],par[maxn],son[maxn],sz[maxn],deep[maxn];
    vector<int>e[maxn];
    struct BIT{
        int node[maxn];
        int lb(int x){return x&(-x);}
        void init(){forn(i,maxn)node[i] = 0;}
        void update(int pos,int v){for(int i = pos;i<=n;i+=lb(i))node[i]+=v;}
        int ask(int pos){int sum = 0;for(int i = pos;i;i-=lb(i))sum+=node[i];return sum;} 
    }bit;
    void init(){
        forn(i,maxn){
            son[i] = 0;
            e[i].clear();
        }
        bit.init();
        id = 0;
    }
    void dfs(int u,int pre,int d){
        sz[u] = 1,par[u] = pre,deep[u] = d;
        for(auto v:e[u])if(v!=pre){
            dfs(v,u,d+1);
            sz[u]+=sz[v];
            if(sz[son[u]]<sz[v]) son[u] = v;
        }
    }
    void getpos(int u,int gg){
        top[u] = gg,p[u] = ++id;
        if(son[u]) getpos(son[u],gg);
        for(auto v:e[u])if(v!=par[u]&&v!=son[u]){
            getpos(v,v);
        }
    }
    void change(int x,int y,int v){
        int fx = top[x],fy = top[y];
        while(fx!=fy){
            if(deep[fx]<deep[fy]) swap(x,y),swap(fx,fy);
            bit.update(p[fx],v);
            bit.update(p[x]+1,-v);
            x = par[fx],fx = top[x];
        }
        if(deep[x]>deep[y]) swap(x,y);
        //cerr<<x<<' '<<p[x]<<' '<<v<<'
    ';
        bit.update(p[x],v);
        bit.update(p[y]+1,-v);
    }
    int main(){
        IO;
        while(cin>>n>>m>>q){
            init();
            for1(i,n) cin>>a[i];
            forn(i,m){
                int x,y;cin>>x>>y;
                e[x].push_back(y);
                e[y].push_back(x);
            }
            dfs(1,0,0);
            getpos(1,1);
            for1(i,n){
                bit.update(p[i],a[i]);
                bit.update(p[i]+1,-a[i]);
            }
            while(q--){
                char c;cin>>c;
                if(c=='Q'){
                    int x;cin>>x;   
                    cout<<bit.ask(p[x])<<'
    ';
                }else{  
                    int x,y,z;cin>>x>>y>>z;
                    if(c=='D') z = -z;
                    change(x,y,z);
                }
            }
        }
        return 0;
    }
    
    人一我百,人十我万。
  • 相关阅读:
    1,300萬像素Xperia TX K.O.相機 東方日報
    信息检索Reading List
    雷军:小米二为何不用1300万像素相机_TechWeb
    1300万像素高清双核旗舰 索尼LT30p评测_手机_科技时代_新浪网
    Darts: DoubleARray Trie System海 的 声音我的搜狐
    说说底层架构之实体类的设计
    不忘本~枚举
    两种底层数据层操作时的架构方式,你喜欢那种?
    说说C#中的global
    JS对外部文件的加载及对IFRMAME的加载的实现,当加载完成后,指定指向方法(方法回调)
  • 原文地址:https://www.cnblogs.com/AlexPanda/p/12520303.html
Copyright © 2011-2022 走看看