Live2d Test Env

HDU - 5571 :tree (动态点分治 异或)

题意:给定一棵树,有点权a[],有边权。 现在有M次修改点权的操作,输出每次修改后,Σ(a[i]^a[j])*dis(i,j);

思路:因为待修改,我们需要快速得到以及修改一个点到其他所有点的信息。 肯定就是动态点分治了啊。  

而异或这个操作没有什么累加的性质,所以每一位拆开单独计算。 根据二进制位置和01区别,先建立14*2点分树。然后每次在同一位置,不同值的树上累加答案。

因为计算dis的过程会重复很多次,所以可以用个dd数组,减少重复统计,然后就用1400ms变成 了960ms。

#include<bits/stdc++.h>
#define FOR() for(int i=Laxt[u];i;i=Next[i])
#define ll long long
#define rep(i,w,v) for(int i=w;i<=v;i++)
using namespace std;
const int maxn=30010;
int Laxt[maxn],Next[maxn<<1],To[maxn<<1],Len[maxn<<1],cnt;
int a[maxn],sz[maxn],son[maxn],dep[maxn];
int Top[maxn],fa[maxn],Fa[maxn],vis[maxn],root,SZ;
ll G[maxn][14][2],F[maxn][14][2],ans,dis[maxn]; //
int num[maxn][14][2],mx;
void init(int N)
{
    cnt=0; rep(i,1,N) Laxt[i]=0;
    rep(i,1,N) vis[i]=0; ans=0;
    rep(i,1,N) rep(j,0,13) rep(k,0,1)
       G[i][j][k]=F[i][j][k]=num[i][j][k]=0;
}
void add(int u,int v,int len)
{
    Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=len;
}
void dfs1(int u,int f)
{
    sz[u]=1; dep[u]=dep[f]+1; fa[u]=f; son[u]=0;
    for(int i=Laxt[u];i;i=Next[i]){
        int v=To[i]; if(v==f) continue;
        dis[v]=dis[u]+Len[i];
        dfs1(v,u); sz[u]+=sz[v];
        if(sz[son[u]]<sz[v]) son[u]=v;
    }
}
void dfs2(int u,int tp)
{
    Top[u]=tp;
    if(son[u]) dfs2(son[u],tp);
    FOR()
        if(To[i]!=fa[u]&&To[i]!=son[u])
            dfs2(To[i],To[i]);
}

int LCA(int u,int v)
{
    while(Top[u]^Top[v]) dep[Top[u]]<dep[Top[v]]?v=fa[Top[v]]:u=fa[Top[u]];
    return dep[u]<dep[v]?u:v;
}
ll getdis(int u,int v){return dis[u]+dis[v]-2*dis[LCA(u,v)];}
void Getroot(int u,int ff)
{
    sz[u]=1;int ret=0;
    FOR(){
        int v=To[i];if(v==ff||vis[v])continue;
        Getroot(v,u);sz[u]+=sz[v];
        ret=max(ret,sz[v]);
    }
    ret=max(ret,SZ-sz[u]);
    if(ret<mx) mx=ret,root=u;
}
void DFS(int u,int ff)
{
    vis[u]=true; Fa[u]=ff;
    FOR(){
        int v=To[i];if(vis[v])continue;
        mx=SZ=sz[v];
        Getroot(v,u);
        DFS(root,u);
    }
}
ll dd[maxn];
void Modify(int u,int val,int opt)
{
    int t;
    for(int j=u;Fa[j];j=Fa[j]) dd[j]=getdis(u,Fa[j]);
    rep(i,0,13){
        if(val&(1<<i)) t=1;
        else t=0;
        ans=ans+1LL*opt*(1<<i)*G[u][i][t^1];
        for(int j=u;Fa[j];j=Fa[j]){
            ll d=dd[j];
            ans=ans+1LL*opt*(1<<i)*(1LL*d*(num[Fa[j]][i][t^1]-num[j][i][t^1])+G[Fa[j]][i][t^1]-F[j][i][t^1]);
        }
    }
    rep(i,0,13){
        if(val&(1<<i)) t=1;
        else t=0;
        num[u][i][t]+=opt;
        for(int j=u;Fa[j];j=Fa[j]){
            ll d=dd[j];
            G[Fa[j]][i][t]+=d*opt;
            F[j][i][t]+=d*opt;
            num[Fa[j]][i][t]+=opt;
        }
    }
}
int main()
{
    int N,Q,D,E,u,v,l;
    while(~scanf("%d",&N)){
        init(N);
        rep(i,1,N) scanf("%d",&a[i]);
        rep(i,1,N-1){
            scanf("%d%d%d",&u,&v,&l);
            add(u,v,l); add(v,u,l);
        }
        dfs1(1,0); dfs2(1,1);
        SZ=mx=N; Getroot(1,0);
        DFS(root,0);
        rep(i,1,N) Modify(i,a[i],1);
        scanf("%d",&Q);
        while(Q--){
            scanf("%d%d",&D,&E);
            Modify(D,a[D],-1);
            a[D]=E;
            Modify(D,a[D],1);
            printf("%lld\n",ans);
        }
    }
    return 0;
}

 

posted @ 2019-07-19 17:33  nimphy  阅读(275)  评论(0编辑  收藏  举报