• BZOJ4381: [POI2015]Odwiedziny


    Description

    给定一棵n个点的树,树上每条边的长度都为1,第i个点的权值为a[i]。
    Byteasar想要走遍这整棵树,他会按照某个1到n的全排列b走n-1次,第i次他会从b[i]点走到b[i+1]点,并且这一次的步伐大小为c[i]。
    对于一次行走,假设起点为x,终点为y,步伐为k,那么Byteasar会从x开始,每步往前走k步,如果最后不足k步就能到达y,那么他会一步走到y。
    请帮助Byteasar统计出每一次行走时经过的所有点的权值和。

    Input

    第一行包含一个正整数n(2<=n<=50000)。表示节点的个数。
    第二行包含n个正整数,其中第i个数为a[i](1<=a[i]<=10000),分别表示每个点的权值。
    接下来n-1行,每行包含两个正整数u,v(1<=u,v<=n),表示u与v之间有一条边。
    接下来一行包含n个互不相同的正整数,其中第i个数为b[i](1<=b[i]<=n),表示行走路线。
    接下来一行包含n-1个正整数,其中第i个数为c[i](1<=c[i]<n),表示每次行走的步伐大小。

    Output

    包含n-1行,每行一个正整数,依次输出每次行走时经过的所有点的权值和

    Sample Input

    5
    1 2 3 4 5
    1 2
    2 3
    3 4
    3 5
    4 1 5 2 3
    1 3 1 1

    Sample Output

    10
    6
    10
    5
     
    对于k比较大的情况,直接暴力。
    对于k比较小的情况,我们一起计算。
    具体实现看code
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=50010;
    int n,val[maxn],b[maxn],c[maxn],first[maxn],next[maxn<<1],to[maxn<<1],e;
    void AddEdge(int u,int v) {
        to[++e]=v;next[e]=first[u];first[u]=e;
        to[++e]=u;next[e]=first[v];first[v]=e;
    }
    int dep[maxn],anc[maxn][20];
    void dfs(int x,int fa) {
        dep[x]=dep[fa]+1;anc[x][0]=fa;
        rep(i,1,19) anc[x][i]=anc[anc[x][i-1]][i-1];
        ren if(to[i]!=fa) dfs(to[i],x);
    }
    int go(int x,int k) {
        rep(i,0,19) if(k>>i&1) x=anc[x][i];
        return x;
    }
    int lca(int x,int y) {
        if(dep[x]<dep[y]) swap(x,y);
        dwn(i,19,0) if(1<<i<=dep[x]-dep[y]) x=anc[x][i];
        dwn(i,19,0) if(anc[x][i]!=anc[y][i]) x=anc[x][i],y=anc[y][i];
        return x==y?x:anc[x][0];
    }
    int vis[maxn],clo;
    void add(int& ans,int x) {
        if(vis[x]!=clo) ans+=val[x];
        vis[x]=clo;
    }
    int solve(int x,int y,int k) {
        int z=lca(x,y),len=dep[x]+dep[y]-dep[z]*2,ans=0;clo++;
        while(1) {
            add(ans,x);int t=go(x,k);
            if(dep[t]>=dep[z]) x=t;
            else break;
        }
        add(ans,y);y=go(y,len%k);
        while(dep[y]>dep[z]) {
            add(ans,y);int t=go(y,k);
            if(dep[t]>dep[z]) y=t;
            else break;
        }
        return ans;
    }
    int ans[maxn],first2[maxn],id[maxn],next2[maxn],cnt;
    void AddQuery(int c,int i) {
        id[++cnt]=i;next2[cnt]=first2[c];first2[c]=cnt;
    }
    int dis[maxn];
    void dfs2(int x,int fa,int gap) {
        dis[x]=val[x];if(dep[x]>gap) dis[x]+=dis[go(x,gap)];
        ren if(to[i]!=fa) dfs2(to[i],x,gap);
    }
    int main() {
        n=read();rep(i,1,n) val[i]=read();
        rep(i,2,n) AddEdge(read(),read());
        dfs(1,0);int SIZE=10;
        rep(i,1,n) b[i]=read();
        rep(i,2,n) {
            c[i]=read();
            if(c[i]>SIZE) ans[i]=solve(b[i-1],b[i],c[i]);
            else AddQuery(c[i],i);
        }
        rep(i,1,SIZE) if(first2[i]) {
            dfs2(1,0,i);
            for(int j=first2[i];j;j=next2[j]) {
                int u=b[id[j]-1],v=b[id[j]],z=lca(u,v);
                int len=dep[u]+dep[v]-2*dep[z],x=go(u,(dep[u]-dep[z])/i*i);
                ans[id[j]]+=dis[u]-dis[x]+val[x];
                int y=go(v,len%i),w=go(y,(dep[y]-dep[z])/i*i);
                if(y!=v) ans[id[j]]+=val[v];
                ans[id[j]]+=dis[y]-dis[w]+val[w];
                if(x==w) ans[id[j]]-=val[w];
            }
        }
        rep(i,2,n) printf("%d
    ",ans[i]);
        return ~~(0-0);
    }
    View Code
  • 相关阅读:
    Windows下图文详解PHP三种运行方式(php_mod、cgi、fastcgi)
    【强烈推荐】利用NAT、Host-Only双虚拟网卡,实现Virtual Box中CentOS6.3联网
    PHP批量清空删除指定文件夹内容
    MySQL收藏
    Eclipse快捷键与使用技巧总结
    “知乎网”技术方案初探
    PHP数组常用函数
    PHP常用字符串的操作函数
    Linux下,如何给PHP安装pdo_mysql扩展
    PHP二维数组排序(list_order)
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5135680.html
Copyright © 2020-2023  润新知