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
  • 相关阅读:
    安德鲁斯称三步系统相机
    Swift游戏开发实战教程(霸内部信息大学)
    ORA-00911:无效字符错误
    Java对多线程~~~Fork/Join同步和异步帧
    jquery跨域请求解决方案(我们寻找,我还没有添加验证)
    mysql 的load data infile要使用
    完整详细的说明GCD列(一)dispatch_async;dispatch_sync;dispatch_async_f;dispatch_sync_f
    Linux查看非root流程执行
    Android_显示器本身被卸载应用程序
    关于微软公有云Azure会计标准
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7241210.html
Copyright © 2011-2022 走看看