1. 程式人生 > 實用技巧 >[點分樹(動態點分治)] 洛谷P6329 震波

[點分樹(動態點分治)] 洛谷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\n",lastans=Ask(u,v));
    }
    return 0;
}