zoukankan      html  css  js  c++  java
  • bzoj3626

    树链剖分+离线

    思路很好

    看见这种题肯定知道不能直接求,就得在lca上搞事情

    将询问拆成两个,排序,然后离线不断从i=1-n到根的路径上全部+1,每次询问就询问从z到根的路径和

    我们想一想,就可以知道z和i,将i到根的路径全部+1,那么lca的深度就是z到根的权值和,而且这个权值和满足可加性,那么我们把询问拆成两个,1-l-1,1-r,相减就是答案

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 50010, mod = 201314;
    int n, Q, tot, cnt;
    ll ans[N];
    int dfn[N], top[N], size[N], son[N], fa[N], dep[N];
    vector<int> G[N];
    struct query {
        int p, z, id, add;
        bool friend operator < (query A, query B)
        {
            return A.p < B.p;
        }
    } q[N << 1];
    struct seg {
        int tree[N << 2], tag[N << 2];
        void pushdown(int x, int l, int r)
        {
            if(!tag[x]) return;
            int mid = (l + r) >> 1;
            tree[x << 1] += (mid - l + 1) * tag[x];
            tree[x << 1 | 1] += (r - mid) * tag[x];
            tag[x << 1] += tag[x];
            tag[x << 1 | 1] += tag[x];
            tag[x] = 0;
        }
        void update(int l, int r, int x, int a, int b, int delta)
        {
            if(l > b || r < a) return;
            if(l >= a && r <= b)
            {
                tag[x] += delta;
                tree[x] += (r - l + 1) * delta;
                return;
            }
            pushdown(x, l, r);
            int mid = (l + r) >> 1;
            update(l, mid, x << 1, a, b, delta);
            update(mid + 1, r, x << 1 | 1, a, b, delta);
            tree[x] = tree[x << 1] + tree[x << 1 | 1];
        }
        int query(int l, int r, int x, int a, int b)
        {
            if(l > b || r < a) return 0;
            if(l >= a && r <= b) return tree[x];
            pushdown(x, l, r);
            int mid = (l + r) >> 1;
            return (query(l, mid, x << 1, a, b) + query(mid + 1, r, x << 1 | 1, a, b));
        }
    } t;
    void dfs(int u, int last)
    {
        size[u] = 1;
        for(int i = 0; i < G[u].size(); ++i)
        {
            int v = G[u][i];
            if(v == last) continue;
            dep[v] = dep[u] + 1;
            fa[v] = u;
            dfs(v, u);
            size[u] += size[v];
            if(size[v] > size[son[u]]) son[u] = v;
        }
    } 
    void dfs(int u, int last, int acs)
    {
        dfn[u] = ++cnt;
        top[u] = acs;
        if(son[u]) dfs(son[u], u, acs);
        for(int i = 0; i < G[u].size(); ++i)
        {
            int v = G[u][i];
            if(v == last || v == son[u]) continue;
            dfs(v, u, v);
        }
    }
    void change(int u)
    {
        while(top[u] != 1)
        {
            t.update(1, n, 1, dfn[top[u]], dfn[u], 1);
            u = fa[top[u]];
        }
        t.update(1, n, 1, 1, dfn[u], 1);
    }
    ll que(int u)
    {
        ll ret = 0;
        while(top[u] != 1) 
        {
            ret += t.query(1, n, 1, dfn[top[u]], dfn[u]);
            u = fa[top[u]];
        }
        ret += t.query(1, n, 1, 1, dfn[u]);
        return ret;
    }
    int main()
    {
        scanf("%d%d", &n, &Q);
        for(int i = 2; i <= n; ++i)
        {
            int u;
            scanf("%d", &u);
            ++u;
            G[i].push_back(u);
            G[u].push_back(i);
        }
        for(int i = 1; i <= Q; ++i)
        {
            int l, r, z;
            scanf("%d%d%d", &l, &r, &z);
            ++l;
            ++r;
            ++z;    
            q[++tot].id = i;
            q[tot].p = l - 1;
            q[tot].z = z;
            q[tot].add = -1;
            q[++tot].id = i;
            q[tot].p = r;
            q[tot].z = z;
            q[tot].add = 1;
        }
        dfs(1, 0);
        dfs(1, 0, 1);
        sort(q + 1, q + tot + 1);
        int p = 0;
        while(q[p + 1].p == 0) ++p;
        for(int i = 1; i <= n; ++i)
        {
            change(i);
            while(q[p + 1].p == i) 
            {
                ++p;
                ans[q[p].id] += que(q[p].z) * q[p].add;
            }
        }
        for(int i = 1; i <= Q; ++i)
            printf("%lld
    ", (ans[i] % mod + mod) % mod);
        return 0;
    }
    View Code
  • 相关阅读:
    51nod 1445 变色DNA ( Bellman-Ford算法求单源最短路径)
    51nod 1307 绳子与重物 (标记父节点更新即可)
    AOJ GRL_1_C: All Pairs Shortest Path (Floyd-Warshall算法求任意两点间的最短路径)(Bellman-Ford算法判断负圈)
    AOJ GRL_1_B: Shortest Path
    AOJ GRL_1_A: Single Source Shortest Path (Dijktra算法求单源最短路径,邻接表)
    【算法】prim算法(最小生成树)(与Dijkstra算法的比较)
    【算法】Dijkstra算法(单源最短路径问题)(路径还原) 邻接矩阵和邻接表实现
    【算法】Bellman-Ford算法(单源最短路径问题)(判断负圈)
    面试之二:Redis是单线程还是多线程?以及处理模型。
    面试之一:CMS收集器整理
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7241210.html
Copyright © 2011-2022 走看看