• 城市漫游-牛客


    题解:u - v这条简单路径上的边会经过奇数次,其余的边会经过偶数次,因为从简单路径中的点出去后还得回来。直接算的话每次询问都得搜整棵树,显然效率是极其低的。如果先预处理出整棵树的边都经过偶数次的花费V,那么答案就等于 V — 简单路径中的边经过偶数次的花费 + 简单路径中的边经过奇数次的代价。下一步是得到后两项,借助LCA,维护路径的前缀和就ok了。

    注意取模!!!!!!

    #include<bits/stdc++.h>
    #define ll long long
    #define P pair<int,int>
    #define pb push_back
    #define lson root << 1
    #define INF (int)2e9 + 7
    #define maxn (int)1e5 + 7
    #define rson root << 1 | 1
    #define LINF (unsigned long long int)1e18
    #define mem(arry, in) memset(arry, in, sizeof(arry))
    using namespace std;
    
    const ll mod = 1000000007;
    
    int n, m, tot;
    int head[maxn], pa[maxn][20], d[maxn];
    ll odd[maxn], even[maxn];
    
    struct node{
        int to, next, va, t;
    }g[maxn << 1];
    
    void Inite()
    {
        tot = 0;
        mem(pa, -1);
        mem(head, -1);
    }
    
    void addedge(int u, int v, int w, int t){
        g[tot].t = t;
        g[tot].to = v;
        g[tot].va = w;
        g[tot].next = head[u];
        head[u] = tot++;
    }
    
    void DFS(int u, int p){
        pa[u][0] = p;
        for(int i = head[u]; i != -1; i = g[i].next){
            int v = g[i].to;
            if(v == p) continue;
            d[v] = d[u] + 1;
    
            int t = g[i].t;
            int w = g[i].va;
            if(t % 2){
                odd[v] = (odd[u] + (ll)t * (ll)w % mod) % mod;
                even[v] = (even[u] + (ll)(t + 1) * (ll)w % mod) % mod;
            }
            else{
                odd[v] = (odd[u] + (ll)(t + 1) * (ll)w % mod) % mod;
                even[v] = (even[u] + (ll)t * (ll)w % mod) % mod;
            }
            DFS(v, u);
        }
    }
    
    void compute(){
        DFS(1, -1);
        for(int i = 1; (1 << i) <= n; i++) {
            for(int j = 1; j <= n; j++) if(pa[j][i - 1] != -1) {
                pa[j][i] = pa[pa[j][i - 1]][i - 1];
            }
        }
    }
    
    int Lct(int u, int v){
        if(d[u] > d[v]) swap(u, v);
        for(int i = 0; i < 20; i++) {
            if(((d[v] - d[u]) >> i) & 1) v = pa[v][i];
        }
        if(u == v) return u;
        for(int i = 19; i >= 0; i--) {
            if(pa[u][i] != pa[v][i]){
                u = pa[u][i];
                v = pa[v][i];
            }
        }
        return pa[u][0];
    }
    
    int main()
    {
        Inite();
        scanf("%d", &n);
    
        ll res = 0;
        for(int i = 1; i < n; i++) {
            int x, y, z, t;
            scanf("%d %d %d %d", &x, &y, &z, &t);
            addedge(x, y, z, t);
            addedge(y, x, z, t);
            if(t % 2) t++;
            res += (ll)t * (ll)z;
            res %= mod;
        }
    
        compute();
    
        scanf("%d", &m);
        for(int i = 0; i < m; i++) {
            int u, v;
            scanf("%d %d", &u, &v);
            int p = Lct(u, v);
    
            ll a1 = ((even[u] - even[p] + mod) % mod + (even[v] - even[p] + mod) % mod) % mod;
            ll a2 = ((odd[u] - odd[p] + mod) % mod + (odd[v] - odd[p] + mod) % mod) % mod;
            printf("%lld
    ", (res - a1 + a2 + mod) % mod);
        }
    
        return 0;
    }
  • 相关阅读:
    「算法笔记」斜率优化
    「算法笔记」多项式求逆
    「算法笔记」霍尔定理
    「算法笔记」Min_25 筛
    「算法笔记」点分治
    「算法笔记」生成函数入门
    「算法笔记」快速数论变换(NTT)
    Spring Boot+Vue全栈开发实战PDF+源代码
    宅米网性能优化实践
    PHP 性能分析第一篇: Xhprof & Xhgui 介绍
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/9219204.html
Copyright © 2020-2023  润新知