• BZOJ4381 : [POI2015]Odwiedziny


    设$lim=sqrt{n}$。

    若$k<lim$,预处理出:

    $F[i][x]$:$x$往上走$i$步到达的点。

    $S[i][x]$:$x$不断往上走$i$步经过的点的和。

    直接$O(1)$查询即可。

    若$kgeq lim$:

    查询时用树链剖分划分为$O(log n)$条重链,在每条重链上暴力往上跳。

    时间复杂度$O(log n+sqrt{n})$。


    总时间复杂度$O(nsqrt{n})$。

    #include<cstdio>
    const int N=50010,M=224;
    int n,lim,i,j,x,y,a[N],b[N],g[N],v[N<<1],nxt[N<<1],ed;
    int d[N],f[N],size[N],son[N],top[N],loc[N],seq[N],dfn;
    int F[M][N],S[M][N];
    inline void swap(int&a,int&b){int c=a;a=b;b=c;}
    inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
    void dfs(int x){
      S[1][x]=S[1][F[1][x]=f[x]]+a[x];
      for(int i=2;i<lim;i++)S[i][x]=S[i][F[i][x]=f[F[i-1][x]]]+a[x];
      d[x]=d[f[x]]+1,size[x]=1;
      for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
        f[v[i]]=x,dfs(v[i]),size[x]+=size[v[i]];
        if(size[v[i]]>size[son[x]])son[x]=v[i];
      }
    }
    void dfs2(int x,int y){
      top[x]=y,seq[loc[x]=++dfn]=x;
      if(son[x])dfs2(son[x],y);
      for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]&&v[i]!=son[x])dfs2(v[i],v[i]);
    }
    inline int lca(int x,int y){
      while(top[x]!=top[y]){
        if(d[top[x]]<d[top[y]])swap(x,y);
        x=f[top[x]];
      }
      return d[x]<d[y]?x:y;
    }
    inline int father(int x,int y){
      while(loc[x]-loc[top[x]]<y){
        y-=loc[x]-loc[top[x]]+1;
        x=f[top[x]];
      }
      return seq[loc[x]-y];
    }
    inline int up(int x,int y,int k){
      y=father(x,d[x]-d[y]-(d[x]-d[y])%k);
      if(k<lim)return S[k][x]-S[k][y]+a[y];
      int t=0,i;
      while(top[x]!=top[y]){
        for(i=loc[x];i>=loc[top[x]];i-=k)t+=a[seq[i]];
        x=father(x,loc[x]-i);
      }
      for(i=loc[x];i>=loc[y];i-=k)t+=a[seq[i]];
      return t;
    }
    inline int query(int x,int y,int k){
      int z=lca(x,y),t=up(x,z,k);
      if((d[x]+d[y]-d[z]*2)%k)t+=a[y];
      if(z==y)return t;
      if((d[x]-d[z])%k==0)t-=a[z];
      int tmp=((d[z]-d[x])%k+k)%k;
      if(d[y]-d[z]-tmp<0)return t;
      return t+up(father(y,(d[y]-d[z]-tmp)%k),z,k);
    }
    int main(){
      scanf("%d",&n);
      while(lim*lim<n)lim++;
      for(i=1;i<=n;i++)scanf("%d",&a[i]);
      for(i=1;i<n;i++)scanf("%d%d",&x,&y),add(x,y),add(y,x);
      dfs(1),dfs2(1,1);
      for(i=1;i<=n;i++)scanf("%d",&b[i]);
      for(i=1;i<n;i++)scanf("%d",&x),printf("%d
    ",query(b[i],b[i+1],x));
      return 0;
    }
    

      

  • 相关阅读:
    python基础-第十二篇-12.1jQuery基础与实例
    python基础-第十一篇-11.2DOM为文档操作
    [LC] 170. Two Sum III
    [Algo] 11. Rainbow Sort
    [LC] 31. Next Permutation
    [LC] 994. Rotting Oranges
    [LC] 863. All Nodes Distance K in Binary Tree
    [Algo] 132. Deep Copy Undirected Graph
    [LC] 138. Deep Copy Linked List With Random Pointer
    [Algo] 118. Array Deduplication IV
  • 原文地址:https://www.cnblogs.com/clrs97/p/5271141.html
Copyright © 2020-2023  润新知