zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    编码问题
    apache 2.4 httpd 2.4.6 反向代理后端的服务为HTTPS https 基于centos7
    ucore系统 eclipse-cdt实验环境准备
    openshift v1.5 不能登录system:admin 问题
    filebeat v6.3 如何增加ip 字段
    filebeat v6.3 多行合并的步骤 多个表达式同时匹配
    如何一步步使用国内yum源一键安装openstack-ocata版本基于centos7
    windows 定时删除N天前日志脚本
    logrotate 如何执行日志按照大小切分
    virtualbox 基于nat模式搭建局域网并且和宿主机通信
  • 原文地址:https://www.cnblogs.com/clrs97/p/5271141.html
Copyright © 2011-2022 走看看