题目信息
一年一度的数据结构发明大赛开始了,小张作为数据结构爱好者积极参加了这次比赛。他将自己参与竞赛的数据结构命名为"虚假的树状数组"。有别于我们常说的树状数组,这个数据结构没有什么实际作用,但还是比较有意思的,因此他光荣的获得了此次大赛的鼓励奖。
"虚假的树状数组"是一个 n 个结点的有向树,每个结点都有一个权值,编号为 i 的结点权值为 ai 。树上的每一个结点可以生成一个数组,生成的方式为:[编号为 x 的结点的生成数组]=[ ax ]+[ x 结点编号最小的儿子结点的生成数组]+…+[ x 结点编号最大的儿子结点的生成数组]。式子中的加号为数组的拼接,例如[1,1,2,1]+[1,2,2,3]=[1,1,2,1,1,2,2,3]
。
同时,有些结点拥有一个排序标记,拥有排序标记的结点的生成数组需要按照从小到大的顺序排序。
现在,请你求出有向树的根节点的生成数组。
输入
第一行一个整数 n(1 ≤ n ≤ 200000)
。
第二行 n 个整数,第 i 个整数 ai(1 ≤ a_i ≤ 10^9)
表示编号为 i 的结点权值。
第三行 n 个整数,第 i 个整数 fi(0 ≤ fi ≤ 1)
,0表示编号为 i 的结点没有排序标记,1表示编号为 i 的结点有排序标记。
接下来 n-1 行,每行两个数 x,y(1 ≤ x,y ≤ n)
,表示编号为x的结点到编号为 y 的结点有一条有向边。数据保证为一个有向树。
输出
用逗号隔开的 n 个整数,表示有向树的根节点的生成数组。用[]括起来。
测试样例
7
12 1 10 8 8 11 2
0 0 0 0 1 0 0
2 3
2 4
2 5
3 1
3 6
5 7
[1,10,12,11,8,2,8]
解答
#include <iostream>
#include <vector>
#include <algorithm>
#define MAXN 200010
using namespace std;
int n;
class Point
{
public:
int num;
int flag;
};
Point points[MAXN];
vector<int> v[MAXN], g[MAXN];
int Root[MAXN];
int root;
struct Rule
{
bool operator()(const Point &a, const Point &b) const
{
return a.num < b.num;
}
};
void dfs(int x)
{
v[x].push_back(points[x].num);//将取到的这个点的确切对应的数值压入新图中
for (int i = 0; i < g[x].size(); i++)
{
//遍历原图中每一个小节点
int tmp = g[x][i];
dfs(tmp);//对每个存在的小节点进行搜索
for (int j = 0; j < v[tmp].size(); j++)
{
//逐个将此节点的子节点拷贝到这里,来建立逐层的关系表
v[x].push_back(v[tmp][j]);
}
}
if (points[x].flag)
{
//如果图上这个点被标记需要排序,那么此处图底下的所有元素都进行排序
sort(v[x].begin(), v[x].end());
}
}
int main()
{
//freopen("E://test.txt", "r", stdin);
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> points[i].num;
}
for (int i = 1; i <= n; i++)
{
cin >> points[i].flag;
}
for (int i = 1; i < n; i++)
{
//输入的内容存储至g
int tmpx, tmpy;
cin >> tmpx >> tmpy;
g[tmpx].push_back(tmpy);//生成图,建立单向连接的表
Root[tmpy]++;//在后边出现的表示其有被指向属性
}
for (int i = 1; i < n; i++)
{
if (Root[i] == 0)
{
//找根
root = i;
}
}
for (int i = 1; i <= n; i++)
{
//将每一个父节点的所有小节点进行排序
sort(g[i].begin(), g[i].end());
}
if (points[root].flag == 1)
{
//此时为根节点需要排序的情况,即直接对所有数字排序即可
sort(points + 1, points + n + 1, Rule());
cout << "[" << points[1].num;
for (int i = 2; i <= n; i++)
{
cout << "," << points[i].num;
}
cout << "]" << endl;
return 0;
}
else
{
dfs(root);//从根节点开始搜索
cout << "[" << v[root][0];
for (int i = 1; i < v[root].size(); i++)
{
cout << "," << v[root][i];
}
cout << "]" << endl;
return 0;
}
}