地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3965

题目:

iven two depth-first-search (DFS) sequences of a binary tree, can you find a binary tree which satisfies both of the DFS sequences?

Recall that a binary tree is a tree in which each vertex has at most two children, and the depth-first search is a tree traversing method which starts at the root and explores as far as possible along each branch before backtracking.

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first line contains an integer n (1 ≤ n ≤ 105), indicating the number of vertices in the binary tree.

The second line contains n integers a1a2, ..., an (1 ≤ ai ≤ n, ∀ 1 ≤ i < j ≤ nai ≠ aj), indicating the first DFS sequence of the binary tree.

The third line of each test case contains n integers b1b2, ..., bn (1 ≤ bi ≤ n, ∀ 1 ≤ i < j ≤ nbi ≠ bj), indicating the second DFS sequence of the binary tree.

It is guaranteed that the sum of n over all test cases does not exceed 106, and there always exists at least one possible binary tree.

We kindly remind you that this problem contains large I/O file, so it's recommended to use a faster I/O method. For example, you can use scanf/printf instead of cin/cout in C++.

Output

For each test case, output one line which contains n integers seperated by one space. The i-th integer indicates the father of the i-th vertex in the binary tree which satisfies both of the DFS sequence. If the i-th vertex is the root of the binary tree, output 0 as its father. If there are multiple valid answers, you can output any of them.

Please, DO NOT print extra spaces at the end of each line, or your program may get a "wrong answer" verdict as this problem is special judged.

Sample Input

2
6
3 4 2 5 1 6
3 4 5 2 1 6
3
1 2 3
1 2 3

Sample Output

3 4 0 3 4 1
0 1 2 思路:

通过上图(第一个dfs序列记为a,第二个记为b)
可以看出对于一个没有兄弟节点的节点x,他必然是紧跟在x的父亲节点f的后面。
对于一个有兄弟节点的节点x(兄弟节点记为y),节点x或y必然紧跟在父亲节点f的后面。
 所以可以得出结论:通过对比父亲节点后面第一个点是否相同,我们可以判断这父亲节点有几个儿子节点。
  如果父亲节点f有两个子节点,但在ab数列中都是先访问左儿子,后访问右儿子,这时似乎结论错了,通过结论只能判断出只有一个子节点。
  但这时可以把右儿子当左儿子的子孙节点的儿子节点,这时构造出的树依旧符合两个dfs序列。
这时怎么判断是知道了,但是怎么确定父亲节点呢?
  对于在数列ab中f的下一个位置的数相同,则f有一个儿子,那么在数列ab中f的下一个位置就是下一个父亲节点。
  如果在数列ab中f的下一个位置的数不同,则f有两个儿子x,y,把x,y当做下一个父亲节点进行递归就好了。
  那怎么确定x和y在ab数列中的位置呢?哈希一下即可。
现在可以通过函数solve(int x,int y,int fa),进行递归判断fa后面的节点a[x],b[y]是否相同来确定fa的子节点个数。
void solve(int x,int y,int fa)
{
ans[a[x]]=ans[b[y]]=fa;
if(x>=n||y>=n)return ;
if(a[x]==b[y])
solve(x+,y+,a[x]);
else
{
solve(x+,hb[a[x]]+,a[x]);//hb是哈希x在b中位置
solve(ha[b[y]]+,y+,b[y]);//ha同理
}
}

但是如果有如下数列:

  ab.....c......xxxxxx

  ac.....b......xxxxxx

上面的代码会出现问题,其递归过程是

这时从第一数列递归访问完区间bc内的数后,本应该直接return,但代码却还是会继续访问

所以函数还需要加入一个参数,访问的最远距离,可以sz代表第一个数列中能访问到的最远位置。

并且当a[x]!=b[y]时还应递归访问xxxxx。

最终代码如下:

 void solve(int x,int y,int fa,int sz)
{
if(x>sz)return;
ans[a[x]]=ans[b[y]]=fa;
if(a[x]==b[y]) sum[fa]+=;
else sum[fa]+=;
if(x==sz)return;
if(a[x]==b[y])
solve(x+,y+,a[x],sz);
else
{
int ta,tb;
ta=ha[b[y]]-,tb=hb[a[x]]-y+ta;
if(x!=ta)
solve(x+,hb[a[x]]+,a[x],ta);
if(y!=hb[a[x]]-)
solve(ta+,y+,b[y],tb);
if(tb!=sz)
solve(tb+,tb+-x+y,fd(ans[a[x]]),sz);
}
}

完整代码:

 #include <bits/stdc++.h>

 using namespace std;

 #define MP make_pair
#define PB push_back
#define ll first
#define rr second
typedef long long LL;
typedef pair<int,int> PII;
const double eps=1e-;
const double pi=acos(-1.0);
const int K=1e6+;
const int mod=1e9+; int n,a[K],b[K],sum[K],ans[K];
int ha[K],hb[K]; int fd(int x)
{
return sum[x]==?fd(ans[x]):x;
}
void solve(int x,int y,int fa,int sz)
{
if(x>sz)return;
ans[a[x]]=ans[b[y]]=fa;
if(a[x]==b[y]) sum[fa]+=;
else sum[fa]+=;
if(x==sz)return;
if(a[x]==b[y])
solve(x+,y+,a[x],sz);
else
{
int ta,tb;
ta=ha[b[y]]-,tb=hb[a[x]]-y+ta;
if(x!=ta)
solve(x+,hb[a[x]]+,a[x],ta);
if(y!=hb[a[x]]-)
solve(ta+,y+,b[y],tb);
if(tb!=sz)
solve(tb+,tb+-x+y,fd(ans[a[x]]),sz);
}
}
int main(void)
{
std::ios::sync_with_stdio(false);
std::cin.tie();
int t;
cin>>t;
while(t--)
{
cin>>n;
for(int i=;i<=n;i++)
cin>>a[i],ha[a[i]]=i,sum[i]=;
for(int i=;i<=n;i++)
cin>>b[i],hb[b[i]]=i;
solve(,,,n);
for(int i=;i<n;i++)
cout<<ans[i]<<" ";
cout<<ans[n]<<endl;
}
return ;
}

2017浙江省赛 H - Binary Tree Restoring ZOJ - 3965的更多相关文章

  1. 2017浙江省赛 E - Seven Segment Display ZOJ - 3962

    地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3962 题目: A seven segment display, or ...

  2. 2017浙江省赛 D - Let's Chat ZOJ - 3961

    地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3961 题目: ACM (ACMers' Chatting Messe ...

  3. ZOJ 3965 Binary Tree Restoring

    Binary Tree Restoring 思路: 递归 比较a序列和b序列中表示同一个子树的一段区间,不断递归 代码: #include<bits/stdc++.h> using nam ...

  4. zoj 3965 Binary Tree Restoring(搜索)

    Binary Tree Restoring Time Limit: 1 Second      Memory Limit: 65536 KB      Special Judge Given two ...

  5. 北邮校赛 H. Black-white Tree (猜的)

    H. Black-white Tree 2017- BUPT Collegiate Programming Contest - sync 时间限制 1000 ms 内存限制 65536 KB 题目描述 ...

  6. 2017浙江省赛 A - Cooking Competition ZOJ - 3958

    地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3958 题目: "Miss Kobayashi's Drag ...

  7. 2017浙江省赛 C - What Kind of Friends Are You? ZOJ - 3960

    地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3960 题目: Japari Park is a large zoo ...

  8. 2017浙江省赛 B - Problem Preparation ZOJ - 3959

    地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3959 题目: It's time to prepare the pr ...

  9. 2015 浙江省赛 H - May Day Holiday

    H - May Day Holiday As a university advocating self-learning and work-rest balance, Marjar Universit ...

随机推荐

  1. w.5 Y k J.COm 9 如何做好总经理助理

    总经理助理的工作职责:(指要做的事—做事的责任) 忠诚的总管家----总经理的代言人和执行官. 总经理助理一方面要为企业发展运筹帷幄,另一方面更要分担繁重的行政事务,所以他务必履行对该职业的使命感. ...

  2. 【NLP】新词发现

    http://www.csdn.net/article/2013-05-08/2815186 http://blog.csdn.net/yuyu2223/article/details/7725705 ...

  3. React Native开发技术

    http://www.lcode.org/react-native-week-issue22/

  4. elasticsearch性能因素总结

    一:硬件方面   在预算充足的情况下.特别是一些高并发业务的搜索.硬件层面占用整个elasticsearch性能空间很大比例. 1)内存: 单实例的情况下,尽量分配32G,排序和统计都是以及内存计算的 ...

  5. Linux 下8种优秀的屏幕录制机

    导读 屏幕录制机已经成为常见的和良好的实践来记录一个重要桌面会话,例如,你想玩一个难度较大的游戏,并且向记录是如何完成的,或者你打算创建一个视频教程,入门文章或指南,或任何其他活动和记录你的桌面会话, ...

  6. 自动交互式脚本--expect

    我们经常会遇到一些需要与服务器程序打交道的场景,比如,从登陆某个服务器,然后进行某项工作.这很平常,但是如果把这个工作自动化进行,你就需要一个程序能自动做你要告诉机器的事情,这样,我们的expect就 ...

  7. 【BZOJ2500】幸福的道路 树形DP+RMQ+双指针法

    [BZOJ2500]幸福的道路 Description 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光. 他们画出了晨练路线的草图,眼尖的 ...

  8. Windows MFC 打开文本

    MFC的CFileDialog自动封装了文件相关的对话框,提供一种简单的文件打开和文件存盘对话框功能. 要使用CFileDialog类,首先要构造一个对象, 项目实例: CFileDialog fil ...

  9. .c和.h的联系

    .c文件就是C语言系列的源文件,而H文件则是C语言的头文件,即C系列中存放函数和全局变量的文件,因为C中的函数是被封装起来的,即无法看到其代码. 子程序不要定义在*.h中.函数定义要放在*.c中,而* ...

  10. 污染Bootstrap modal 通过 css选择器 避免

    w 对框架的掌握.改进. 0-存在重复代码,需要改正,js timepicker框架传入类名: 1-大量的点击块,怎样避免对每个块重复写modal? <style> .w > td ...