• bzoj3626: [LNOI2014]LCA (树链剖分)


     很神奇的方法

     感觉是有生之年都想不到正解的这种

     考虑对i 到根的节点权值 + 1,则从根到z的路径和就是lca(i,z)的深度

     所以依次把0 ~ n - 1的点权值 + 1

     对于询问[l, r] 这个区间关于z 的深度和,就用(1, r) - (1, l - 1)的值表示

     详见黄学长的博客啦

     http://hzwer.com/3415.html

     下面给出代码

    #include <cstdio>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int N = 50000 + 10;
    const int MOD = 201314;
      
    struct Query {
        int u, id, z, flag;
        inline bool operator < (const Query &o) const {
            return u < o.u;
        }
    } Q[N * 2];
    int n, q, tot, cnt;
    int sz[N], dep[N], fa[N], hs[N], top[N], pos[N];
    vector < int > E[N];
      
    #define isdigit(x) (x >= '0' && x <= '9')
    inline void read(int &ans) {
        ans = 0;
        static char buf = getchar();
        for (; !isdigit(buf); buf = getchar());
        for (; isdigit(buf); buf = getchar())
            ans = ans * 10 + buf - '0';
    }
      
    void dfs1(int x, int d, int f) {
        dep[x] = d; fa[x] = f;
        sz[x] = 1;  hs[x] = -1;
        int tmp = 0;
        for (int i = 0; i < E[x].size(); i++) {
            int u = E[x][i];
            dfs1(u, d + 1, x);
            if (sz[u] > tmp)
                hs[x] = u, tmp = sz[u];
            sz[x] += sz[u];
        }
    }
      
    void dfs2(int x, int t) {
        top[x] = t; pos[x] = ++tot;
        if (hs[x] == -1)    return ;
        dfs2(hs[x], t);
        for (int i = 0; i < E[x].size(); i++)
            if (E[x][i] != hs[x])
                dfs2(E[x][i], E[x][i]);
    }
      
    int add[N * 3], sum[N * 3];
    #define g(l, r) (l + r | l != r) 
    #define o g(l, r)
    #define ls g(l, mid)
    #define rs g(mid + 1, r)
      
    inline void pushDown(int l, int r) {
        if (!add[o] || l == r)  return ;
        int mid = l + r >> 1;
        add[ls] += add[o]; 
        sum[ls] += add[o] * (mid - l + 1);
        add[rs] += add[o];
        sum[rs] += add[o] * (r - mid);
        add[o] = 0;
    }
      
    inline void pushUp(int l, int r) {
        int mid = l + r >> 1;
        sum[o] = sum[ls] + sum[rs];
    }
      
    void modify(int l, int r, int L, int R) {
        if (l >= L && r <= R) {
            sum[o] += r - l + 1;
            add[o]++;
            return ;
        }
        pushDown(l, r);
        int mid = l + r >> 1;
        if (L <= mid)    modify(l, mid, L, R);
        if (R > mid) modify(mid + 1, r, L, R);
        pushUp(l, r);
    }
      
    inline void modify(int x, int y) {
        int f1 = top[x], f2 = top[y];
        while (f1 != f2) {
            if (dep[f1] < dep[f2])
                swap(x, y), swap(f1, f2);
            modify(1, n, pos[f1], pos[x]);
            x = fa[f1]; f1 = top[x];
        }
        if (dep[x] > dep[y]) swap(x, y);
        modify(1, n, pos[x], pos[y]);
    }
      
    int query(int l, int r, int L, int R) {
        if (l >= L && r <= R) return sum[o];
        pushDown(l, r);
        int mid = l + r >> 1;
        int ans = 0;
        if (L <= mid)    ans += query(l, mid, L, R);
        if (R > mid) ans += query(mid + 1, r, L, R);
        return ans;
    }
      
    inline int query(int x, int y) {
        int f1 = top[x], f2 = top[y];
        int ans = 0;
        while (f1 != f2) {
            if (dep[f1] < dep[f2])
                swap(x, y), swap(f1, f2);
            ans = (ans + query(1, n, pos[f1], pos[x])) % MOD;
            x = fa[f1]; f1 = top[x];
        }
        if (dep[x] > dep[y]) swap(x, y);
        ans = (ans + query(1, n, pos[x], pos[y])) % MOD;
        return ans;
    }
      
    int ans1[N], ans2[N];
    int main() {
        read(n); read(q);
        for (int i = 1; i < n; i++) {
            int x; read(x); 
            E[x].push_back(i);
        }
        dfs1(0, 1, -1); dfs2(0, 0);
        for (int i = 1; i <= q; i++) {
            int l, r, z;
            read(l); read(r); read(z);  
            Q[++cnt] = (Query) {l - 1, i, z, 0};
            Q[++cnt] = (Query) {r, i, z, 1};
        }
        sort(Q + 1, Q + cnt + 1);
        int now = -1;
        for (int i = 1; i <= cnt; i++) {
            while (now < Q[i].u) ++now, modify(now, 0);
            if (!Q[i].flag)  ans1[Q[i].id] = query(Q[i].z, 0);
            else    ans2[Q[i].id] = query(Q[i].z, 0);
        }
        for (int i = 1; i <= q; i++)
            printf("%d
    ", (ans2[i] - ans1[i] + MOD) % MOD);
        return 0;
    }
  • 相关阅读:
    PhysX3 User Guide 04 Rigid Body Dynamics
    PhysX3 User Guide 05 Scene Queries
    PhysX3 User Guide 01 基础
    error C2061: syntax error : identifier '__RPC__out_xcount_part'
    vim中替换字符串
    Linker Tools Warning LNK4098
    PhysX3 User Guide 03 Joint
    【转】C RunTime Library 暨 深入理解编译选项的含义 04
    不足
    tortoiseSVN Check out正常但Show Log时 Go Offline
  • 原文地址:https://www.cnblogs.com/cminus/p/8598193.html
Copyright © 2020-2023  润新知