[CF893F] Subtree Minimum Query-President Tree

Test address: Subtree Minimum Query
Given a tree with roots, each node has a weight. Now there are several queries. Each query gives x, K x, k, which means that in the sub-tree with roots of X x, the distance between x x and K K is not more than the minimum weight. Mandatory online.
Practice: This topic needs to use the President Tree.
First, we must ask the subtree to sort the points in the order of DFS, and then each query asks the minimum weight of all points in the order of DFS numbered in [l,r][l,r], in the depth of [dep(x),dep(x)+k][dep(x),dep(x)+k]. Noting that there must be no point in [l,r][l,r] which is deeper than dep(x)dep(x), the problem is transformed into finding the minimum weights of all points in [l,r][l,r], depth in [0,dep(x)+k][0,dep(x)+k] in the DFS sequence. Then we build the presidential tree in depth order, and ask the minimum interval in a certain version every time.
The following is my code:

#include <bits/stdc++.h>
#define inf 1000000001
using namespace std;
int n,r,m,a[100010],first[100010],tot=0,dep[100010],top[100010],q[100010],h,t,maxdep=0;
int rt[1000010],mn[20000010],ch[20000010][2],lft[100010],rht[100010],pos[100010],tim=0;
struct edge {int v,next;} e[200010];
bool vis[100010]={0};

void insert(int a,int b)
{
    e[++tot].v=b,e[tot].next=first[a],first[a]=tot;
}

void bfs()
{
    vis[r]=1;dep[r]=0;
    q[1]=r;h=t=1;
    while(h<=t)
    {
        int v=q[h++];
        top[dep[v]]=h-1;
        maxdep=max(maxdep,dep[v]);
        for(int i=first[v];i;i=e[i].next)
            if (!vis[e[i].v])
            {
                q[++t]=e[i].v;
                dep[e[i].v]=dep[v]+1;
                vis[e[i].v]=1;
            }
    }
}

void dfs(int v,int f)
{
    lft[v]=++tim;
    pos[tim]=v;
    for(int i=first[v];i;i=e[i].next)
        if (e[i].v!=f) dfs(e[i].v,v);
    rht[v]=tim;
}

void pushup(int x)
{
    mn[x]=min(mn[ch[x][0]],mn[ch[x][1]]);
}

void build(int &v,int l,int r)
{
    v=++tot;
    if (l==r) {mn[v]=inf;return;}
    int mid=(l+r)>>1;
    build(ch[v][0],l,mid);
    build(ch[v][1],mid+1,r);
    pushup(v);
}

void treeinsert(int &v,int last,int l,int r,int x)
{
    v=++tot;
    mn[v]=mn[last];
    ch[v][0]=ch[last][0],ch[v][1]=ch[last][1];
    if (l==r) {mn[v]=a[pos[x]];return;}
    int mid=(l+r)>>1;
    if (x<=mid) treeinsert(ch[v][0],ch[last][0],l,mid,x);
    else treeinsert(ch[v][1],ch[last][1],mid+1,r,x);
    pushup(v);
}

int treequery(int v,int l,int r,int s,int t)
{
    if (l>=s&&r<=t) return mn[v];
    int mid=(l+r)>>1,ans=inf;
    if (s<=mid) ans=min(ans,treequery(ch[v][0],l,mid,s,t));
    if (t>mid) ans=min(ans,treequery(ch[v][1],mid+1,r,s,t));
    return ans;
}

int main()
{
    scanf("%d%d",&n,&r);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        insert(x,y),insert(y,x);
    }

    bfs();
    dfs(r,0);
    tot=0;
    build(rt[0],1,n);
    for(int i=1;i<=n;i++)
        treeinsert(rt[i],rt[i-1],1,n,lft[q[i]]);

    scanf("%d",&m);
    int last=0;
    while(m--)
    {
        int x,k;
        scanf("%d%d",&x,&k);
        x=(x+last)%n+1,k=(k+last)%n;
        last=treequery(rt[top[min(dep[x]+k,maxdep)]],1,n,lft[x],rht[x]);
        printf("%d\n",last);
    }

    return 0;
}

Posted by LordTyphon on Wed, 06 Feb 2019 01:24:16 -0800