zoukankan      html  css  js  c++  java
  • 【LNOI 2014】 LCA

    【题目链接】

             点击打开链接

    【算法】

               考虑求lca(x,y)的深度

               我们可以将从根到x路径上的点都打上标记,然后,询问y到根上路径的权值和

               那么,求sigma(depth(lca(i,z)))(l <= i <= r ),我们可以将区间[l,r]中的点依次打上标记,然后,询问点z到根路径

               上的权值和

               因为此题有多组询问,显然在线很难做,因此,我们考虑离线计算答案

               求sigma(depth(lca(i,z))) (l <= i <= r),我们可以转化为

               sigma(depth(lca(i,z))) ( 0 <= i <= r) - sigma(depth(lca(i,z))) (0 <= i <= l - 1)

               那么,树链剖分/动态树都可以解决这道题,树链剖分的时间复杂度是O((n + q) log(n)^2)的,而动态树的时间复杂度是             O((n + q) log(n))的

    【代码】

               由于笔者太弱,不会动态树,所以这份代码是树链剖分的写法

             

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXM 50010
    const int P = 201314;
    
    struct Edge
    {
        int to,nxt;
    } e[MAXM];
    struct Query
    {
        int pos,opt,z,id;    
    } q[MAXM*2];
    
    int i,n,m,f,timer,tot,cnt,now,l,r,z;
    int dfn[MAXM],size[MAXM],top[MAXM],head[MAXM],son[MAXM],ans[MAXM],fa[MAXM];
    
    struct SegmentTree
    {
            struct Node
            {
                    int l,r;
                    int sum,tag;
            } Tree[MAXM*4];
            inline void build(int index,int l,int r)
            {
                    int mid;
                    Tree[index].l = l; Tree[index].r = r;
                    Tree[index].sum = Tree[index].tag = 0;
                    if (l == r) return;
                    mid = (l + r) >> 1;
                    build(index<<1,l,mid);
                    build(index<<1|1,mid+1,r);
            }
            inline void pushdown(int index)
            {
                    int l = Tree[index].l,r = Tree[index].r;
                    int mid = (l + r) >> 1;
                    if (Tree[index].tag)
                    {
                            Tree[index<<1].sum = (Tree[index<<1].sum + (mid - l + 1) * Tree[index].tag) % P;
                            Tree[index<<1|1].sum = (Tree[index<<1|1].sum + (r - mid) * Tree[index].tag) % P;
                            Tree[index<<1].tag = (Tree[index<<1].tag + Tree[index].tag) % P;
                            Tree[index<<1|1].tag = (Tree[index<<1|1].tag + Tree[index].tag) % P;
                            Tree[index].tag = 0;
                    }
            }
            inline void update(int index)
            {
                    Tree[index].sum = (Tree[index<<1].sum + Tree[index<<1|1].sum) % P;
            }
            inline void modify(int index,int l,int r,int val)
            {
                    int mid;
                    if (Tree[index].l == l && Tree[index].r == r)
                    {
                            Tree[index].sum = (Tree[index].sum + (r - l + 1) * val) % P;
                            Tree[index].tag = (Tree[index].tag + val) % P;
                            return;
                    }
                    pushdown(index);
                    mid = (Tree[index].l + Tree[index].r) >> 1;
                    if (mid >= r) modify(index<<1,l,r,val);
                    else if (mid + 1 <= l) modify(index<<1|1,l,r,val);
                    else
                    {
                            modify(index<<1,l,mid,val);
                            modify(index<<1|1,mid+1,r,val);
                    }
                    update(index);
            }
            inline int query(int index,int l,int r)
            {
                    int mid;
                    if (Tree[index].l == l && Tree[index].r == r) return Tree[index].sum;
                    pushdown(index);
                    mid = (Tree[index].l + Tree[index].r) >> 1;
                    if (mid >= r) return query(index<<1,l,r);
                    else if (mid + 1 <= l) return query(index<<1|1,l,r);
                    else return (query(index<<1,l,mid) + query(index<<1|1,mid+1,r)) % P;
            }
    } T;
    inline bool cmp(Query a,Query b) 
    {
        return a.pos < b.pos;
    }
    inline void add(int u,int v)
    {
            tot++;
            e[tot] = (Edge){v,head[u]};
            head[u] = tot;
    }
    inline void dfs1(int u)
    {
            int i,v;
            size[u] = 1;
            for (i = head[u]; i; i = e[i].nxt)
            {
                    v = e[i].to;
                    dfs1(v);
                    size[u] += size[v];
                    if (size[v] > size[son[u]] || !son[u]) son[u] = v;
            }
    }
    inline void dfs2(int u,int tp)
    {
            int i,v;
            top[u] = tp;
            dfn[u] = ++timer;
            if (son[u]) dfs2(son[u],tp);     
            for (i = head[u]; i; i = e[i].nxt)
            {
                    v = e[i].to;
                    if (son[u] != v) dfs2(v,v);
            }
    }
    inline void modify(int pos)
    {
            int tp = top[pos];
            while (tp)
            {
                    T.modify(1,dfn[tp],dfn[pos],1);
                    pos = fa[tp]; tp = top[pos];
            }
            T.modify(1,1,dfn[pos],1);
    }
    inline int query(int pos)
    {
            int tp = top[pos],ans = 0;
            while (tp)
            {
                    ans = (ans + T.query(1,dfn[tp],dfn[pos])) % P;
                    pos = fa[tp]; tp = top[pos];
            }
            ans = (ans + T.query(1,1,dfn[pos])) % P;
            return ans;
    }
    
    int main()
    {
        
            scanf("%d%d",&n,&m);
            for (i = 1; i < n; i++) 
            {
                    scanf("%d",&fa[i]);
                    add(fa[i],i);    
            }
            dfs1(0);
            dfs2(0,0);
            T.build(1,1,timer);
            for (i = 1; i <= m; i++) 
            {
                    scanf("%d%d%d",&l,&r,&z);
                    if (l != 0) q[++cnt] = (Query){l-1,-1,z,i};
                    q[++cnt] = (Query){r,1,z,i};
            }
            sort(q+1,q+cnt+1,cmp);
            now = -1; 
            for (i = 1; i <= cnt; i++)
            {
                    while (now + 1 <= q[i].pos) 
                    {
                            now++;
                            modify(now);
                    } 
                    if (q[i].opt == 1) ans[q[i].id] = (ans[q[i].id] + query(q[i].z)) % P;
                    else ans[q[i].id] = (ans[q[i].id] - query(q[i].z) + P) % P;
            }
            for (i = 1; i <= m; i++) printf("%d
    ",ans[i]);
            
            return 0;
    }
  • 相关阅读:
    什么是webview
    juqery.fn.extend和jquery.extend
    LeetCode
    5. Longest Palindromic Substring
    42. Trapping Rain Water
    11. Container With Most Water
    621. Task Scheduler
    49. Group Anagrams
    739. Daily Temperatures
    3. Longest Substring Without Repeating Characters
  • 原文地址:https://www.cnblogs.com/evenbao/p/9196302.html
Copyright © 2011-2022 走看看