• 「LNOI2014」LCA


    传送门

    这里要用到一个巧妙的想法:我们可以把加上 (dep_u) 转化为节点到根路径加和路径查询。

    然后题目要求的是一段区间编号的点对某个点求 ( ext{LCA}),可以考虑离线,然后我们把这道题转化成了树上路径加以及查询。

    写个树剖就没了。

    参考代码:

    #include <algorithm>
    #include <cstdio>
    using namespace std;
    
    const int _ = 1e5 + 5, mod = 201314;
    
    template < class T > void read(T& s) {
        s = 0; int f = 0; char c = getchar();
        while ('0' > c || c > '9') f |= c == '-', c = getchar();
        while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
        s = f ? -s : s;
    }
    
    int tot, head[_]; struct Edge { int v, nxt; } edge[_ << 1];
    void Add_edge(int u, int v) { edge[++tot] = (Edge) { v, head[u] }, head[u] = tot; }
    
    int n, q, ans[_], cnt;
    struct node { int x, y, opt, id; } t[_ << 1];
    int cmp(node a, node b) { return a.x < b.x; }
    int dep[_], siz[_], son[_], dfn[_], top[_], fa[_], sum[_ << 2], tag[_ << 2];
    
    int lc(int p) { return p << 1; }
    
    int rc(int p) { return p << 1 | 1; }
    
    void pushup(int p) { sum[p] = (sum[lc(p)] + sum[rc(p)]) % mod; }
    
    void add(int p, int v, int l, int r) {
        sum[p] = (sum[p] + v * (r - l + 1) % mod) % mod, tag[p] = (tag[p] + v) % mod;
    }
    
    void pushdown(int p, int l, int r, int mid) {
        if (tag[p]) add(lc(p), tag[p], l, mid), add(rc(p), tag[p], mid + 1, r), tag[p] = 0;
    }
    
    void update(int ql, int qr, int v, int p = 1, int l = 1, int r = n) {
        if (ql <= l && r <= qr) return add(p, v, l, r);
        int mid = (l + r) >> 1;
        pushdown(p, l, r, mid);
        if (ql <= mid) update(ql, qr, v, lc(p), l, mid);
        if (qr > mid) update(ql, qr, v, rc(p), mid + 1, r);
        pushup(p);
    }
    
    int query(int ql, int qr, int p = 1, int l = 1, int r = n) {
        if (ql <= l && r <= qr) return sum[p];
        int mid = (l + r) >> 1, res = 0;
        pushdown(p, l, r, mid);
        if (ql <= mid) res = (res + query(ql, qr, lc(p), l, mid)) % mod;
        if (qr > mid) res = (res + query(ql, qr, rc(p), mid + 1, r)) % mod;
        return res;
    }
    
    void dfs(int u, int f) {
        dep[u] = dep[f] + 1, siz[u] = 1, fa[u] = f;
        for (int i = head[u]; i; i = edge[i].nxt) {
            int v = edge[i].v; if (v == f) continue ;
            dfs(v, u), siz[u] += siz[v];
            if (siz[son[u]] < siz[v]) son[u] = v;
        }
    }
    
    void dfs(int u, int f, int topf) {
        top[u] = topf, dfn[u] = ++dfn[0];
        if (son[u]) dfs(son[u], u, topf);
        for (int i = head[u]; i; i = edge[i].nxt) {
            int v = edge[i].v; if (v == f || v == son[u]) continue ;
            dfs(v, u, v);
        }
    }
    
    void Update(int x) {
        int fx = top[x];
        while (fx != 1)
            update(dfn[fx], dfn[x], 1), x = fa[fx], fx = top[x];
        update(1, dfn[x], 1);
    }
    
    int Query(int x) {
        int fx = top[x], res = 0;
        while (fx != 1)
            res = (res + query(dfn[fx], dfn[x])) % mod, x = fa[fx], fx = top[x];
        return (res + query(1, dfn[x])) % mod;
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("cpp.in", "r", stdin), freopen("cpp.out", "w", stdout);
    #endif
        read(n), read(q);
        for (int x, i = 2; i <= n; ++i) read(x), ++x, Add_edge(x, i), Add_edge(i, x);
        dfs(1, 0), dfs(1, 0, 1);
        for (int l, r, x, i = 1; i <= q; ++i) {
            read(l), ++l, read(r), ++r, read(x), ++x;
            t[++cnt] = (node) { r, x, 1, i };
            t[++cnt] = (node) { l - 1, x, -1, i };
        }
        sort(t + 1, t + cnt + 1, cmp);
        int p = 0;
        for (int i = 1; i <= cnt; ++i) {
            while (p < t[i].x) Update(++p);
            ans[t[i].id] = (ans[t[i].id] + t[i].opt * Query(t[i].y) + mod) % mod;
        }
        for (int i = 1; i <= q; ++i) printf("%d
    ", ans[i]);
        return 0;
    }
    
  • 相关阅读:
    Use Eclipse to develop groovy[docs.codehaus.org]
    Map.putAll方法——追加另一个Map对象到当前Map集合(转)
    限制某个进程只能在某个CPU上运行
    Java实现蓝桥杯 算法提高 身份证号码升级
    Java实现蓝桥杯 算法提高 身份证号码升级
    Java实现蓝桥杯 算法提高 身份证号码升级
    Java实现蓝桥杯 算法提高 身份证号码升级
    Java蓝桥杯 算法训练 复数归一化
    Java实现 蓝桥杯 算法提高 最大乘积
    Java实现 蓝桥杯 算法训练 p1103
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/13125087.html
Copyright © 2020-2023  润新知