zoukankan      html  css  js  c++  java
  • [POI2015] Odwiedziny

    [题目链接]

              https://www.lydsy.com/JudgeOnline/problem.php?id=4381

    [算法]

            考虑分块 , 先设一个阈值B = 200

            记Su , i表示从u节点开始 , 每次向上跳i步 , 所经过点的权值和 , 可以在O(NBlogN)时间内预处理

            对于每次询问 , 若k <= B , 可以通过预处理的值求出答案 , 否则暴力处理

            时间复杂度 : O(NBlogN)(取B = 200)

    [代码]

           

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    #define N 50010
    #define M 250
    #define MAXLOG 20
    
    struct edge {
            int to , nxt;
    } e[N << 1];
    
    int n , tot , MAGIC;
    int a[N] , b[N] , c[N] , father[N][MAXLOG] , depth[N] , head[N];
    ll cnt[N][M];
    
    template <typename T> inline void chkmax(T &x,T y) { 
            x = max(x,y); 
    }
    template <typename T> inline void chkmin(T &x,T y) { 
            x = min(x,y); 
    }
    template <typename T> inline void read(T &x) {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline void addedge(int u , int v) {
            ++tot;
            e[tot] = (edge){v , head[u]};
            head[u] = tot;
    }
    inline void work(int u , int par) {
            father[u][0] = par;
            depth[u] = depth[par] + 1;
            for (int i = 1; i < MAXLOG; ++i) {
                    father[u][i] = father[father[u][i - 1]][i - 1];
            }        
            for (int i = head[u]; i; i = e[i].nxt) {
                    int v = e[i].to;
                    if (v == par) continue;
                    work(v , u);
            }
    }
    inline int get(int u , int k) {
            for (int i = 0; i < MAXLOG; ++i) {
                    if (k & (1 << i))
                          u = father[u][i];
            }
            return u;
    }
    inline void dfs(int u , int par) {
            for (int i = 1; i <= MAGIC; ++i) {
                    cnt[u][i] = a[u] + cnt[get(u , i)][i];
            }
            for (int i = head[u]; i; i = e[i].nxt) {
                    int v = e[i].to;
                    if (v == par) continue;
                    dfs(v , u);
            }
    }
    inline int lca(int x , int y) {
            if (depth[x] > depth[y]) swap(x , y);
            for (int i = MAXLOG - 1; i >= 0; --i) {
                    if (depth[father[y][i]] >= depth[x])
                            y = father[y][i];
            }        
            if (x == y) return x;
            for (int i = MAXLOG - 1; i >= 0; --i) {
                    if (father[x][i] != father[y][i])
                            x = father[x][i] , y = father[y][i];
            }
            return father[x][0];
    }
    
    int main()
    {
            
            read(n);
            for (int i = 1; i <= n; ++i) read(a[i]);
            for (int i = 1; i < n; ++i) {
                    int x , y;
                    read(x); read(y);
                    addedge(x , y);
                    addedge(y , x);
            }
            for (int i = 1; i <= n; ++i) read(b[i]);
            for (int i = 2; i <= n; ++i) read(c[i]);
            MAGIC = (int)sqrt(n);
            work(1 , 0);
            dfs(1 , 0);
            for (int i = 2; i <= n; ++i) {
                    int x = b[i - 1] , y = b[i];
                    int Lca = lca(x , y);
                    ll ans = 0;
                    if (Lca == x) {
                            if (c[i] <= MAGIC) {
                                    int R = (depth[y] - depth[x]) % c[i];
                                    if (R > 0) ans += a[y];
                                    y = get(y , R);
                                    int val = (depth[y] - depth[x]) / c[i] + 1;
                                    ans += cnt[y][c[i]] - cnt[get(y , val * c[i])][c[i]]; 
                            } else {
                                    int R = (depth[y] - depth[x]) % c[i];
                                    if (R > 0) ans += a[y];
                                    y = get(y , R);
                                    while (depth[y] >= depth[x]) {
                                            ans += a[y];
                                            y = get(y , c[i]);
                                    }
                            }
                    } else if (Lca == y) {
                            if (c[i] <= MAGIC) {
                                    int val = (depth[x] - depth[y]) / c[i] + 1;
                                    ans += cnt[x][c[i]] - cnt[get(x , val * c[i])][c[i]];
                            } else {
                                    while (depth[x] >= depth[y]) {
                                            ans += a[x];
                                            x = get(x , c[i]);
                                    }
                            }
                    } else if (c[i] <= MAGIC) {
                            int val = (depth[x] - depth[Lca]) / c[i] + 1;
                            ans += cnt[x][c[i]] - cnt[get(x , val * c[i])][c[i]];
                            int pre = get(x , (val - 1) * c[i]);
                            int R = (depth[pre] - depth[Lca] + depth[y] - depth[Lca]) % c[i];
                            if (R != 0) {
                                    int now = get(y , R);
                                    val = (depth[now] - depth[Lca]) / c[i] + 1;
                                    ans += a[y] + cnt[y][c[i]] - cnt[get(y , val * c[i])][c[i]]; 
                            } else {
                                    val = (depth[y] - depth[Lca]) / c[i] + 1;
                                    ans += cnt[y][c[i]] - cnt[get(y , val * c[i])][c[i]];
                                    if ((depth[x] - depth[Lca]) % c[i] == 0) ans -= a[Lca];
                            } 
                    } else {
                            while (depth[x] >= depth[Lca]) {
                                    ans += a[x];
                                    if (depth[x] - c[i] < depth[Lca]) break;
                                    else x = get(x , c[i]);
                            }
                            int R = (depth[x] - depth[Lca] + depth[y] - depth[Lca]) % c[i];
                            if (R != 0) {
                                    ans += a[y];
                                    y = get(y , R);
                                    while (depth[y] >= depth[Lca]) {
                                            ans += a[y];
                                            y = get(y , c[i]);
                                    }
                            } else {
                                    while (depth[y] >= depth[Lca]) {
                                            ans += a[y];
                                            y = get(y , c[i]);
                                    }
                                    if (x == Lca) ans -= a[Lca];
                            }
                    }
                    printf("%lld
    " , ans);
            }
            
            return 0;
        
    }
  • 相关阅读:
    Binary Tree Zigzag Level Order Traversal
    Binary Tree Level Order Traversal
    Symmetric Tree
    Best Time to Buy and Sell Stock II
    Best Time to Buy and Sell Stock
    Triangle
    Populating Next Right Pointers in Each Node II
    Pascal's Triangle II
    Pascal's Triangle
    Populating Next Right Pointers in Each Node
  • 原文地址:https://www.cnblogs.com/evenbao/p/10778232.html
Copyright © 2011-2022 走看看