zoukankan      html  css  js  c++  java
  • [USACO11DEC] 牧草种植Grass Planting

    https://www.luogu.org/problemnew/show/3038

    将为边加权转化成为点加权

    对于每条边,我们将其深度更大的端点加权,则区间 [l, r] 的加权(或询问)即为去掉深度最小的点,给其余点加权(或询问)。

    1)最后一次树剖查询时,当前两点 x,y 必定在同一重链上(y 的深度小于 x);

    2)根据处理前的 dfs 序,我们是优先遍历重儿子,那么重儿子在线段树中的编号一定紧邻其父节点(即为其父节点编号 + 1),则我们要忽略深度最小的那个点 y ,即为处理区间 [ y 在线段树中的编号 + 1, x 在线段树中的编号](另外还要注意的是,y = x 时在线段树内执行会出错,我们要特判这种情况) 。

    #include <bits/stdc++.h>
    
    using namespace std;
    const int N = 1e5 + 10;
    
    #define gc getchar()
    #define lson jd << 1
    #define rson jd << 1 | 1 
    
    struct Node_1{
        int v, nxt;
    }G[N << 1];
    struct Node_2{
        int fa, son, deep, topp, siz, tree;
    }P[N];
    struct Node_3{
        int l, r, w, f;
    }T[N << 2];
    int n, Ti, now = 1, head[N], tim, ans;
    
    inline int read(){
        int x = 0; char c = gc;
        while(c < '0' || c > '9') c = gc;
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
        return x;
    }
    
    inline void add(int u, int v){
        G[now].v = v;
        G[now].nxt = head[u];
        head[u] = now ++;
    }
    
    void dfs_find_son(int u, int fa, int dep){
        P[u].fa = fa;
        P[u].deep = dep;
        P[u].siz = 1;
        for(int i = head[u]; ~ i; i = G[i].nxt){
            int v = G[i].v;
            if(v != fa){
                dfs_find_son(v, u, dep + 1);
                P[u].siz += P[v].siz;
                if(P[v].siz > P[P[u].son].siz) P[u].son = v;
            }
        }
    }
    
    void dfs_to_un(int u, int tp){
        P[u].topp = tp;
        P[u].tree = ++ tim;
        if(!P[u].son) return ;
        dfs_to_un(P[u].son, tp);
        for(int i = head[u]; ~ i; i = G[i].nxt){
            int v = G[i].v;
            if(v != P[u].son && v != P[u].fa) dfs_to_un(v, v);
        }
    }
    
    void down(int jd){
        int F = T[jd].f;
        T[lson].w += (T[lson].r - T[lson].l + 1) * F; T[lson].f += F;
        T[rson].w += (T[rson].r - T[rson].l + 1) * F; T[rson].f += F;
        T[jd].f = 0; 
    }
    
    void Sec_G(int l, int r, int jd, int x, int y){
        if(x <= l && r <= y){
            int yj = r - l + 1;
            T[jd].w += yj;
            T[jd].f ++;
            return ;
        }
        if(T[jd].f) down(jd);
        int mid = (l + r) >> 1;
        if(x <= mid) Sec_G(l, mid, lson, x, y);
        if(y > mid) Sec_G(mid + 1, r, rson, x, y);
    }
    
    void Sec_G_imp(int x, int y){
        int tp1 = P[x].topp, tp2 = P[y].topp;
        while(tp1 != tp2){
            if(P[tp1].deep < P[tp2].deep) swap(x, y), swap(tp1, tp2);
            Sec_G(1, n, 1, P[tp1].tree, P[x].tree);
            x = P[tp1].fa;
            tp1 = P[x].topp;
        }
        if(x == y) return ;
        if(P[x].deep > P[y].deep) swap(x, y);
        Sec_G(1, n, 1, P[x].tree + 1, P[y].tree);
    }
    
    void build_tree(int l, int r, int jd){
        T[jd].l = l; T[jd].r = r;
        if(l == r) return ;
        int mid = (l + r) >> 1;
        build_tree(l, mid, lson);
        build_tree(mid + 1, r, rson);
    }
    
    void Sec_A(int l, int r, int jd, int x, int y){
        if(x <= l && r <= y){
            ans += T[jd].w;
            return ;
        }
        if(T[jd].f) down(jd);
        int mid = (l + r) >> 1;
        if(x <= mid) Sec_A(l, mid, lson, x, y);
        if(y > mid) Sec_A(mid + 1, r, rson, x, y);
    }
    
    int Sec_A_imp(int x, int y){
        int ret = 0;
        int tp1 = P[x].topp, tp2 = P[y].topp;
        while(tp1 != tp2){
            if(P[tp1].deep < P[tp2].deep) swap(x, y), swap(tp1, tp2);
            ans = 0;
            Sec_A(1, n, 1, P[tp1].tree, P[x].tree);
            ret += ans;
            x = P[tp1].fa;
            tp1 = P[x].topp;
        }
        if(x == y) return ret;
        ans = 0;
        if(P[x].deep > P[y].deep) swap(x, y);
        Sec_A(1, n, 1, P[x].tree + 1, P[y].tree);
        ret += ans;
        return ret;
    }
    
    int main()
    {
        n = read(); Ti = read();
        for(int i = 1; i <= n; i ++) head[i] = -1;
        for(int i = 1; i < n; i ++) {
            int u = read(), v = read();
            add(u, v); add(v, u);
        }
        dfs_find_son(1, 0, 1);
        dfs_to_un(1, 1);
        build_tree(1, n, 1);
        while(Ti --){
            string s; cin >> s;
            int x = read(), y = read();
            if(s[0] == 'P') Sec_G_imp(x, y);
            else cout << Sec_A_imp(x, y) << endl;
            
        }
        return 0;
    }
  • 相关阅读:
    HDOJ 4747 Mex
    HDU 1203 I NEED A OFFER!
    HDU 2616 Kill the monster
    HDU 3496 Watch The Movie
    Codeforces 347A A. Difference Row
    Codeforces 347B B. Fixed Points
    Codeforces 372B B. Hungry Sequence
    HDU 1476 Sudoku Killer
    HDU 1987 How many ways
    HDU 2564 词组缩写
  • 原文地址:https://www.cnblogs.com/shandongs1/p/8012595.html
Copyright © 2011-2022 走看看