hihocoder 1232 || 2015北京網路賽F題 樹連剖分
http://hihocoder.com/problemset/problem/1232
描述
"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?
輸入
The input consists of no more than 8 test cases.
For each test case:
The first line contains two integers, N and M, indicating the number of vertices and the number of queries.(1≤N,M≤100,000)
The next line contains N−1 integers. It describes the structure of wife tree in this way: If the ith integer is k, it means that the vertex labeled k is the father vertex of the vertex labeled (i+1) . It's guaranteed that a vertex X's father vertex can't have a larger label than X does.
The next line describes the husband tree in the same way.
Then next M lines describe the queries. Each line contains two integers Xi and Yi. Let Ki be the earliest possible meeting vertex of the ith query (K0 is defined as 0). In the ith query, Ada's thumb was put at the vertex labeled (Xi+Ki−1) mod N + 1 and Asa's thumb was put at the vertex labeled (Yi+Ki−1) mod N + 1.(1≤Xi,Yi≤N) at the beginning.
輸出
For each test case:
Output the answer for each query in a single line. The answer contains three integers: the earliest possible meeting vertex, the number of the vertices Ada will encounter and the number of the vertices Asa will encounter (including the starting vertex and the ending vertex). In particular, if they put their thumb at the same vertex at first, the earliest possible meeting vertex should be the starting vertex.
提示
In the first test case:
The wife tree is like this:
The husband tree is like this:
The query is (5)[4], and they may meet at {1,3}, so the earliest one is 3.
In the second test case:
The wife tree is like this:
The husband tree is like this:
The first query is (1)[4], the second query is (2)[1], and the last one is (5)[2].
For the first query, they may only meet at 1.
For the second query, they may only meet at 1.
For the third query, they may meet at {1,2}, the earliest one is 2.
5 1 1 2 3 3 1 1 3 2 4 3 5 3 1 1 2 2 1 2 2 1 5 3 5 4 3 5 5 3 1 1 2 2 1 2 3 1 1 4 1 1 3 4樣例輸出
3 2 2 1 1 3 1 2 1 2 2 1 1 2 2 3 1 1 2 1 2
/**
hihocoder 1232 || 2015北京網路賽F題 樹連剖分
題目大意:有一對夫妻樹,他們的節點個數都一樣,都以1為根節點,並且兩個樹中所有的父親節點的編號都比其子孫節點小。
現在分別給出兩個樹的結構,下面有m組詢問,妻子在妻子樹的x點出發,丈夫在丈夫樹的y點出發,只要二者所到節點的
編號一樣就算相遇,二者只能望父親節點走,問每次二者的最早的相遇節點是什麼,並且求出二者經過的節點的個數
解題思路:樹連剖分後,每次在鏈上找匹配。每棵樹都剖一次,solve裡面兩個迴圈,列舉兩棵樹叢節點到根的鏈。
首先題目裡面有個性質父節點的編號小於子節點,然後就是列舉看兩個鏈L1, L2是否有重複的點。對於每個點i, 找到i
分別在兩棵樹中所在鏈的根f1, f2把i存在 f1, f2中,理論上來說應該用F[f1][f2].push_back(i),但是這樣太大,
而且不是每對f1, f2都有公共點,就用了map,二分查詢。
*/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <vector>
#include <map>
using namespace std;
const int maxn=100500;
int n,m;
vector<int>vec[2][maxn];
int fa[2][maxn],dep[2][maxn],siz[2][maxn],top[2][maxn],son[2][maxn];
map<pair<int,int>,int>mp;
vector<pair<int,int> >ans;
vector<pair<int,int> >::iterator lv[maxn],rv[maxn];
void init()
{
for(int i=0;i<=n;i++)
{
vec[0][i].clear();
vec[1][i].clear();
}
mp.clear();
ans.clear();
}
void dfs1(int u,int pre,int flag)
{
son[flag][u]=0,siz[flag][u]=1;
dep[flag][u]=dep[flag][pre]+1;
fa[flag][u]=pre;
int n=vec[flag][u].size();
for(int i=0;i<n;i++)
{
int v=vec[flag][u][i];
dfs1(v,u,flag);
if(siz[flag][son[flag][u]]<siz[flag][v])
{
son[flag][u]=v;
}
siz[flag][u]+=siz[flag][v];
}
}
void dfs2(int u,int tp,int flag)
{
top[flag][u]=tp;
if(son[flag][u])
{
dfs2(son[flag][u],tp,flag);
}
int n=vec[flag][u].size();
for(int i=0;i<n;i++)
{
int v=vec[flag][u][i];
if(v==son[flag][u])continue;
dfs2(v,v,flag);
}
}
int solve(int x,int y)///分別列舉x和y的所在鏈,找深度最大的同號頂點
{
int fai,faj;
for(int i=x;i;i=fa[0][fai])
{
fai=top[0][i];
for(int j=y;j;j=fa[1][faj])
{
faj=top[1][j];
if(j<fai)break;
if(i<faj)continue;
int t=mp[make_pair(fai,faj)];
if(t==0)continue;
if((rv[t]-1)->second<=min(i,j))
return (rv[t]-1)->second;
else
{
vector<pair<int,int> >::iterator id=upper_bound(lv[t],rv[t],make_pair(t,min(i,j)));
if(id!=lv[t])return (id-1)->second;
}
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
for(int i=1;i<n;i++)///wife tree
{
int x;
scanf("%d",&x);
vec[0][x].push_back(i+1);
}
for(int i=1;i<n;i++)///husband tree
{
int x;
scanf("%d",&x);
vec[1][x].push_back(i+1);
}
for(int i=0;i<2;i++)///分別進行樹鏈剖分
{
dep[i][0]=0;
dfs1(1,0,i);
dfs2(1,1,i);
}
int cnt=0;
for(int i=1;i<=n;i++)///記錄每一個節點在兩個樹中鏈的位置
{
pair<int,int> tmp=make_pair(top[0][i],top[1][i]);
if(mp[tmp]==0)mp[tmp]=++cnt;
ans.push_back(make_pair(mp[tmp],i));
}
sort(ans.begin(),ans.end());
for(int i=1;i<=cnt;i++)
{
lv[i]=lower_bound(ans.begin(),ans.end(),make_pair(i,0));
rv[i]=upper_bound(ans.begin(),ans.end(),make_pair(i,n));
}
int pre=0;
while(m--)
{
int x,y;
scanf("%d%d",&x,&y);
x=(x+pre)%n+1;
y=(y+pre)%n+1;
int ret=solve(x,y);
int ret1=abs(dep[0][x]-dep[0][ret])+1;
int ret2=abs(dep[1][y]-dep[1][ret])+1;
pre=ret;
printf("%d %d %d\n",ret,ret1,ret2);
}
}
return 0;
}
相關文章
- 樹鏈剖分
- 對樹鏈剖分的愛 題解
- [OI] 樹鏈剖分
- hihocoder 1257 Snake Carpet 模擬構造題||2015北京現場賽I題
- 樹鏈剖分模板+入門題 SPOJ - QTREEQT
- 樹鏈剖分總結
- 淺談樹鏈剖分
- bzoj4034: [HAOI2015]樹上操作(樹鏈剖分+線段樹)
- 【筆記/模板】樹鏈剖分筆記
- #8. 「模板」樹鏈剖分
- 樹鏈剖分學習筆記筆記
- 「學習筆記」樹鏈剖分筆記
- codechef Dynamic GCD [樹鏈剖分 gcd]GC
- 2024.3.14 樹鏈剖分
- BF的資料結構題單-提高組——樹鏈剖分資料結構
- P8025 【樹鏈剖分求祖先】
- hihocoder trie 樹
- 專注網格剖分 - TetGen
- 樹剖(不太會)
- hihocoder1224 賽車(樹的深度相關)
- 一起來學習樹鏈剖分吧!
- 重鏈剖分題目選講
- 樹鏈剖分解析
- 2014年北京師範大學新生程式設計競賽網路賽程式設計
- TZOJ 8472 : Tree (重鏈剖分+線段樹) POJ 3237
- 長鏈剖分模板
- 2014北京網路賽1006||hdu5037 思維題
- hihocoder 1260 String Problem I (Trie樹 好題)
- hihocoder 1192 簡單的樹嵌入 (樹上DFS 構造 好題)
- spoj375 樹鏈剖分(單點更新,區間查詢)
- poj 3237 樹鏈剖分(區間更新,區間查詢)
- ACM-ICPC 2018 徐州賽區網路預賽 F. Features TrackACM
- 長鏈剖分筆記筆記
- 『dfn、樹剖雜項』Day9
- HYSBZ 2243 樹鏈剖分(區間更新,區間查詢)較難
- hdu5445 || 2015長春網路賽1009題 多重揹包問題
- 五分鐘瞭解網路連線
- 2024ccpc網路賽補題