"LCA chain tree split."

<> Yes

<First update>


<Text>

LCA

Description

N gives a rooted tree nodes (numbered from 0 to n-1, root node 0). +1 depth is defined from a point of the node to the root.
Provided DEP [i] represents the depth of the point i, LCA (i, j) represents the common ancestor of i and j. There are times query q, each query given LRZ, seeking sigma_ {l <= i <= r} dep [LCA (i, z)]. (I.e., in seeking [l, r] common ancestor node i and for each interval depth z in the sum)

Input Format

The first line of two integers nq. Next row n-1, respectively, the parent node number points 1 to n-1. Next q lines of three integers lrz.

Output Format

Q output lines, each line represents an answer to the inquiry. The answer to each of the output modulo 201314

Sample Input

5 2 
0 
0 
1 
1 
1 4 3
1 4 2

Sample Output

8
5

Resolve

Easy to find a query may ask split into two:
\ [\ sum_ {L} = I ^ rdep [the LCA (I, Z)] = \ sum_ = {I}. 1 ^ rdep [the LCA (I, Z)] - \ sum_ {i = 1} ^ {
l-1} dep [LCA (i, z)] \] are in the form of a prefix and facilitate our process.

And asked for a prefix, we can see that it has a meaningful contribution: that is, each seeking a \ (i \) and \ (z \) the number of common ancestors. Further, we can understand: the each node \ (I \) bit on the right are added to the root of a path seeking \ (Z \) to a point on the right path, and more.

We all know that trees add a direct link and query tree chain chain can be split, but it seems to affect each other between the various inquiries.

最简单的解决方法就是把询问离线。我们之前已经把询问转化为前缀和的形式了,那就把所有询问按照\(r\)排序,这样依次处理询问就没有影响了。

\(Code:\)

#include <bits/stdc++.h>
using namespace std;
const int N = 50020 , Mod = 201314;
struct node { int l,r,tag; long long cnt; };
struct SegmentTree
{
    node ver[N<<2];
    #define l(p) ver[p].l
    #define r(p) ver[p].r
    #define cnt(p) ver[p].cnt
    #define tag(p) ver[p].tag
    inline void build(int p,int l,int r)
    {
        l(p) = l , r(p) = r , cnt(p) = tag(p) = 0;
        if ( l == r ) return;
        int mid = l + r >> 1;
        build( p<<1 , l , mid );
        build( p<<1|1 , mid+1 , r );
    }
    inline void update(int p) { cnt(p) = cnt(p<<1) + cnt(p<<1|1); }
    inline void spread(int p)
    {
        if ( tag(p) )
        {
            tag(p<<1) = ( tag(p<<1) + tag(p) ) % Mod;
            tag(p<<1|1) = ( tag(p<<1|1) + tag(p) ) % Mod;
            cnt(p<<1) = ( cnt(p<<1) + 1LL * ( r(p<<1) - l(p<<1) + 1 ) * tag(p) % Mod ) % Mod;
            cnt(p<<1|1) = ( cnt(p<<1|1) + 1LL * ( r(p<<1|1) - l(p<<1|1) + 1 ) * tag(p) % Mod ) % Mod;
            tag(p) = 0;
        }
    }
    inline void modify(int p,int l,int r,int v)
    {
        if ( l <= l(p) && r >= r(p) )
        {
            cnt(p) = ( cnt(p) + ( r(p) - l(p) + 1 ) * v % Mod ) % Mod;
            tag(p) = ( tag(p) + v ) % Mod; return;
        }
        spread( p );
        int mid = l(p) + r(p) >> 1;
        if ( l <= mid ) modify( p<<1 , l , r , v );
        if ( r > mid ) modify( p<<1|1 , l , r , v );
        update( p );
    }
    inline int query(int p,int l,int r)
    {
        if ( l <= l(p) && r >= r(p) ) return cnt(p);
        spread( p );
        int mid = l(p) + r(p) >> 1 , res = 0;
        if ( l <= mid ) res = ( res + query( p<<1 , l , r ) ) % Mod;
        if ( r > mid ) res = ( res + query( p<<1|1 , l , r ) ) % Mod;
        return res;
    }
};
SegmentTree Tree;
struct edge { int ver,next; } e[N*2];
struct query { int r,z,id,f; } a[N*2];
int n,m,t,Head[N],tot;
int fa[N],dep[N],son[N],size[N],top[N],id[N],cnt;
long long ans[N];
inline void insert(int x,int y)
{
    e[++t] = (edge){y,Head[x]} , Head[x] = t;
    e[++t] = (edge){x,Head[y]} , Head[y] = t;
}
inline int read(void)
{
    int x = 0 , w = 0; char ch = ' ';
    while ( !isdigit(ch) ) w |= ch=='-' , ch = getchar();
    while ( isdigit(ch) ) x = x*10 + ch-48 , ch = getchar();
    return w ? -x : x;
}
inline void input(void)
{
    n = read() , m = read();
    for ( int i = 2 ; i <= n ; i++ )
        insert( i , read() + 1 );
    for ( int i = 1 ; i <= m ; i++ )
    {
        int l = read() + 1 , r = read() + 1 , z = read() + 1;
        a[++tot] = (query){ r , z , i , 1 };
        a[++tot] = (query){ l-1 , z , i , -1 };
    }
}
inline void dfs1(int x,int f,int depth)
{
    fa[x] = f , dep[x] = depth , size[x] = 1;
    int Max = -1;
    for ( int i = Head[x] ; i ; i = e[i].next )
    {
        int y = e[i].ver;
        if ( y == f ) continue;
        dfs1( y , x , depth+1 );
        size[x] += size[y];
        if ( size[y] > Max ) Max = size[y] , son[x] = y;
    }
}
inline void dfs2(int x,int Top)
{
    id[x] = ++cnt , top[x] = Top;
    if ( !son[x] ) return;
    else dfs2( son[x] , Top );
    for ( int i = Head[x] ; i ; i = e[i].next )
    {
        int y = e[i].ver;
        if ( y == fa[x] || y == son[x] ) continue;
        dfs2( y , y );
    }
}
inline void modify_chain(int x,int y,int val)
{
    while ( top[x] ^ top[y] )
    {
        if ( dep[top[x]] < dep[top[y]] ) swap( x , y );
        Tree.modify( 1 , id[top[x]] , id[x] , val );
        x = fa[top[x]];
    }
    if ( dep[x] > dep[y] ) swap( x , y );
    Tree.modify( 1 , id[x] , id[y] , val );
}
inline int query_chain(int x,int y)
{
    int res = 0;
    while ( top[x] ^ top[y] )
    {
        if ( dep[top[x]] < dep[top[y]] ) swap( x , y );
        res = ( res + Tree.query( 1 , id[top[x]] , id[x] ) ) % Mod;
        x = fa[top[x]];
    }
    if ( dep[x] > dep[y] ) swap( x , y );
    return ( res + Tree.query( 1 , id[x] , id[y] ) ) % Mod;
}
inline bool compare(query p1,query p2) { return p1.r < p2.r; }
inline void solve(void)
{
    int p = 0;
    for ( int i = 1 ; i <= tot ; i++ )
    {
        while ( p < a[i].r ) modify_chain( 1 , ++p , 1 );
        ans[ a[i].id ] += a[i].f * query_chain( 1 , a[i].z );
        ans[ a[i].id ] = ( ans[ a[i].id ] % Mod + Mod ) % Mod;
    }
}
int main(void)
{
    input();
    dfs1( 1 , 0 , 1 );
    dfs2( 1 , 1 );
    Tree.build( 1 , 1 , n );
    sort( a+1 , a+tot+1 , compare );
    solve();
    for (int i=1;i<=m;i++)
        printf("%d\n",ans[i]);
    return 0;
}

<后记>

Guess you like

Origin www.cnblogs.com/Parsnip/p/11203765.html