(中等) Hiho 1232 Couple Trees(15年北京网络赛F题),主席树+树链剖分。

时间:2021-04-30 06:33:03

  "Couple Trees" are two trees, a husband tree and a wife tree. They are named because they look like a couple leaning on each other. They share a same root, and their branches are intertwined. In China, many lovers go to the couple trees. Under the trees, lovers wish to be accompanied by a lifetime.

Ada and her boyfriend Asa came to the couple trees as well. They were very interested in the trees. They were all ACMers, so after careful observation, they found out that these two trees could be considered as two "trees" in graph theory. These two trees shared N vertices which were labeled 1 to N, and they all had exactly N vertices. Vertices 1 was the root of both trees.

Ada and Asa wanted to know more about the trees' rough bark, so each of them put one thumb at a vertices. Then they moved their thumbs towards the root. Ada moved along the wife tree, and Asa moved along the husband tree. Of course, they could moved at different speed.

At that moment, a thought suddenly came to Ada's mind: their thumbs may meet before the root. Which one was the earliest possible meeting vertex? And how many vertices would Ada and Asa encounter on the way to the meeting vertex?

  题意差不多就是对于N个点有两棵树,也就是两棵树边不同但是共用所有点,然后询问两个点,问这两个点分别沿着两颗树向根部走,然后路径的交点中最近的那个。

  相当经典的题目,比赛的时候就是没想出来,结果比赛完了一想到主席树这题就会了。。。

  因为每个点都是向着根部走,所以这里应该自然而然想到主席树才对,因为每一个节点都是在其父亲的基础上加了一个点。

  至于维护什么就想了一段时间了。。。

  因为是两棵树,对第一颗树进行树链剖分,得到每个点剖分之后的位置,然后用主席树维护第二棵树的每个点,维护从根节点到这个点所经过的所有的点的树剖之后的位置。

  然后询问的时候就让那个点在第一颗树上跑,每次询问一个区间,然后一直这样得到第一个位置就是了。。。

代码如下:

// ━━━━━━神兽出没━━━━━━
// ┏┓ ┏┓
// ┏┛┻━━━━━━━┛┻┓
// ┃ ┃
// ┃ ━ ┃
// ████━████ ┃
// ┃ ┃
// ┃ ┻ ┃
// ┃ ┃
// ┗━┓ ┏━┛
// ┃ ┃
// ┃ ┃
// ┃ ┗━━━┓
// ┃ ┣┓
// ┃ ┏┛
// ┗┓┓┏━━━━━┳┓┏┛
// ┃┫┫ ┃┫┫
// ┗┻┛ ┗┻┛
//
// ━━━━━━感觉萌萌哒━━━━━━ // Author : WhyWhy
// Created Time : 2015年09月21日 星期一 23时30分54秒
// File Name : F.cpp #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h> using namespace std; const int MaxN=;
const int MaxNode=; int N; struct Chair_Tree
{
int Tcou;
int TreeRoot[MaxN];
int lson[MaxNode],rson[MaxNode];
int BIT[MaxNode]; void insert(int old,int ne,int id)
{
old=TreeRoot[old]; int newRoot=Tcou++;
int L=,R=N,M; TreeRoot[ne]=newRoot;
BIT[newRoot]=max(id,BIT[old]);
while(R>L)
{
M=(L+R)>>;
if(id<=M)
{
lson[newRoot]=Tcou++;
rson[newRoot]=rson[old];
newRoot=lson[newRoot];
old=lson[old];
R=M;
}
else
{
lson[newRoot]=lson[old];
rson[newRoot]=Tcou++;
newRoot=rson[newRoot];
old=rson[old];
L=M+;
}
BIT[newRoot]=max(id,BIT[old]);
}
} int query(int ql,int qr,int L,int R,int po)
{
if(ql<=L && qr>=R)
return BIT[po]; int M=(L+R)>>;
int ret=; if(ql<=M) ret=max(ret,query(ql,qr,L,M,lson[po]));
if(qr>M) ret=max(ret,query(ql,qr,M+,R,rson[po])); return ret;
} int query(int tree,int ql,int qr)
{
return query(ql,qr,,N,TreeRoot[tree]);
} int Build(int L,int R)
{
int root=Tcou++; BIT[root]=;
if(L!=R)
{
int M=(L+R)>>;
lson[root]=Build(L,M);
rson[root]=Build(M+,R);
}
return root;
} void init()
{
Tcou=;
TreeRoot[]=Build(,N);
}
}tree; int fa1[MaxN],fa2[MaxN];
int dep1[MaxN],dep2[MaxN]; struct Edge
{
int to,next;
}; Edge E[MaxN*];
int Ecou,head[MaxN]; int fa[MaxN],dep[MaxN],son[MaxN],siz[MaxN],top[MaxN],w[MaxN],fw[MaxN];
int Tcou; void init()
{
Ecou=;
Tcou=;
w[]=; //!!!
fw[]=; //!!!
top[]=; //!!!
memset(head,-,sizeof(head));
} void addEdge(int u,int v)
{
E[Ecou].to=v;
E[Ecou].next=head[u];
head[u]=Ecou++;
} void dfs1(int u,int pre,int d)
{
int v; dep[u]=d;
fa[u]=pre;
siz[u]=;
son[u]=-; for(int i=head[u];i!=-;i=E[i].next)
if(E[i].to!=pre)
{
v=E[i].to;
dfs1(v,u,d+);
siz[u]+=siz[v]; if(son[u]==- || siz[son[u]]<siz[v])
son[u]=v;
}
} void dfs2(int u)
{
if(son[u]==-)
return; top[son[u]]=top[u];
w[son[u]]=++Tcou;
fw[w[son[u]]]=son[u]; dfs2(son[u]); int v; for(int i=head[u];i!=-;i=E[i].next)
if(E[i].to!=son[u] && E[i].to!=fa[u])
{
v=E[i].to;
top[v]=v;
w[v]=++Tcou;
fw[w[v]]=v; // !!! dfs2(v);
}
} int query(int tr,int u)
{
int f=top[u];
int ret; while((ret=tree.query(tr,w[f],w[u]))==)
{
u=fa[f];
f=top[u];
} return fw[ret];
} int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout); int Q;
int a,b;
int t; while(~scanf("%d %d",&N,&Q))
{
t=;
tree.init();
init();
fa1[]=fa2[]=;
dep1[]=dep2[]=; for(int i=;i<=N;++i)
{
scanf("%d",&a);
addEdge(a,i);
addEdge(i,a);
dep1[i]=dep1[a]+;
}
dfs1(,-,);
dfs2(); tree.insert(,,);
for(int i=;i<=N;++i)
{
scanf("%d",&a);
dep2[i]=dep2[a]+;
tree.insert(a,i,w[i]);
} while(Q--)
{
scanf("%d %d",&a,&b);
a=(a+t)%N+;
b=(b+t)%N+;
t=query(b,a);
printf("%d %d %d\n",t,dep1[a]-dep1[t]+,dep2[b]-dep2[t]+);
}
} return ;
}