zoukankan      html  css  js  c++  java
  • [点分树(动态点分治)] 洛谷P6329 震波

    题目链接
    参考

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define RG register int
    #define LL long long
    
    template<typename elemType>
    inline void Read(elemType &T){
        elemType X=0,w=0; char ch=0;
        while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
        while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        T=(w?-X:X);
    }
    
    const int maxn=100010;
    const int INF=1<<30;
    
    struct Graph{
        struct edge{int Next,to;};
        edge G[maxn<<1];
        int head[maxn],cnt;
        Graph():cnt(2){}
        void clear(int n){cnt=2;fill(head,head+n+2,0);}
        void add_edge(int u,int v){
            G[cnt].to=v;
            G[cnt].Next=head[u];
            head[u]=cnt++;
        }
    };
    
    template<size_t n>
    struct HLD{
        int fa[n],top[n],hson[n],sz[n],deep[n];
        Graph &G;int root;
        HLD(Graph &_G):G(_G){}
        void DFS_Init(int u){
            sz[u]=1;deep[u]=deep[fa[u]]+1;
            for(int i=G.head[u];i;i=G.G[i].Next){
                int v=G.G[i].to;
                if(v==fa[u]) continue;
                fa[v]=u;
                DFS_Init(v);
                sz[u]+=sz[v];
                if(sz[hson[u]]<sz[v]) hson[u]=v;
            }
        }
        void DFS(int u,int anc){
            top[u]=anc;
            if(!hson[u]) return;
            DFS(hson[u],anc);
            for(int i=G.head[u];i;i=G.G[i].Next){
                int v=G.G[i].to;
                if(v==fa[u] || v==hson[u]) continue;
                DFS(v,v);
            }
        }
        void build(int _root){
            root=_root;
            fa[root]=0;DFS_Init(root);DFS(root,root);
        }
        int LCA(int u,int v){
            while(top[u]!=top[v]){
                if(deep[top[u]]<deep[top[v]]) swap(u,v);
                u=fa[top[u]];
            }
            if(deep[u]>deep[v]) swap(u,v);
            return u;
        }
        int getDis(int u,int v){return deep[u]+deep[v]-(deep[LCA(u,v)]<<1);}
    };
    
    template<typename elemType>
    struct BIT{
        inline int lowbit(int x){return x&(-x);}
        int n;vector<elemType> Node;
        void build(int _n){n=_n;Node.resize(n+1);}
        void Update(int x,elemType Add){
            ++x;for(;x<=n;x+=lowbit(x)) Node[x]+=Add;
        }
        elemType PrefixSum(elemType x){
            ++x;x=min(x,n);elemType Res=0;
            for(;x;x-=lowbit(x))
                Res+=Node[x];return Res;
        }
        elemType Query(int L,int R){return PrefixSum(R)-PrefixSum(L-1);}
    };
    
    Graph G;
    HLD<maxn> hld(G);
    BIT<int> TR1[maxn],TR2[maxn];
    int Value[maxn],Size[maxn],Fa[maxn];
    bool vis[maxn];
    int N,M,Root,CurSize,MaxSize;
    
    void GetRoot(int u,int fa){
        Size[u]=1;
        int mx=0;
        for(int i=G.head[u];i;i=G.G[i].Next){
            int v=G.G[i].to;
            if(vis[v] || v==fa) continue;
            GetRoot(v,u);
            Size[u]+=Size[v];
            mx=max(mx,Size[v]);
        }
        mx=max(mx,CurSize-Size[u]);
        if(mx<MaxSize){MaxSize=mx;Root=u;}
    }
    
    void Divide(int u,int fa){
        vis[u]=true;Fa[u]=fa;
        TR1[u].build((CurSize>>1)+1);
        TR2[u].build(CurSize+1);
        for(int i=G.head[u];i;i=G.G[i].Next){
            int v=G.G[i].to;
            if(vis[v]) continue;
            CurSize=MaxSize=Size[v];
            Root=0;GetRoot(v,0);
            Divide(Root,u);
        }
    }
    
    void Change(int u,int v){
        TR1[u].Update(0,v);
        for(int x=u;Fa[x];x=Fa[x]){
            int d=hld.getDis(u,Fa[x]);
            TR1[Fa[x]].Update(d,v);
            TR2[x].Update(d,v);
        }
    }
    
    int Ask(int u,int K){
        int ans=TR1[u].PrefixSum(K);
        for(int x=u;Fa[x];x=Fa[x]){
            int d=hld.getDis(u,Fa[x]);
            if(d>K) continue;
            ans+=TR1[Fa[x]].PrefixSum(K-d);
            ans-=TR2[x].PrefixSum(K-d);
        }
        return ans;
    }
    
    int main(){
        Read(N);Read(M);
        for(int i=1;i<=N;++i)
            Read(Value[i]);
        for(int i=1;i<=N-1;++i){
            int u,v;Read(u);Read(v);
            G.add_edge(u,v);
            G.add_edge(v,u);
        }
        hld.build(1);CurSize=N;
        CurSize=MaxSize=N;Root=0;GetRoot(1,0);
        Divide(Root,0);
        for(int i=1;i<=N;++i)
            Change(i,Value[i]);
        int lastans=0;
        while(M--){
            int opt,u,v;
            Read(opt);Read(u);Read(v);
            u^=lastans;v^=lastans;
            if(opt){Change(u,v-Value[u]);Value[u]=v;}
            else printf("%d
    ",lastans=Ask(u,v));
        }
        return 0;
    }
    
  • 相关阅读:
    《Think in Java》(七)复用类
    书单2017
    React 获取真实Dom v8.6.2版本
    vue-waterfall2 实现瀑布流,及总结的问题
    vue CSS使用/deep/
    vue.config.js 配置 scss,less,sass全局配置 vuecli3
    postcss 将px转换成rem vuecli3+vant+vue+postcss
    px转rem vue vscode
    轮播模仿臭美APP,vue,swiper
    瀑布流 懒加载 组件 vue js
  • 原文地址:https://www.cnblogs.com/AEMShana/p/14105342.html
Copyright © 2011-2022 走看看