zoukankan      html  css  js  c++  java
  • 城市漫游-牛客

    题解: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;
    }
  • 相关阅读:
    POJ3094 UVALive3594 HDU2734 ZOJ2812 Quicksum【进制】
    UVALive5583 UVA562 Dividing coins
    POJ1979 HDU1312 Red and Black【DFS】
    POJ1979 HDU1312 Red and Black【DFS】
    POJ2386 Lake Counting【DFS】
    POJ2386 Lake Counting【DFS】
    HDU4394 Digital Square
    HDU4394 Digital Square
    UVA213 UVALive5152 Message Decoding
    UVA213 UVALive5152 Message Decoding
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/9219204.html
Copyright © 2011-2022 走看看