题目大意为给一个树的DFS序和每个节点的子树大小,让我们还原树。
我们用DFS遍历DFS序的每个节点,对于当前节点 ,如果DFS序的下一个节点的子树大小加上当前节点积累的子节点数小于等于当前节点给定的子树大小,那么说明这有边相连并继续递归,否则退出。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int a[N],b[N];
vector<int>g;
typedef pair<int,int>PII;
set<PII>ans;
int n;
void dfs(int u)
{
int cnt=0;
while(g.size())
{
int c=g.back();
if(b[c]+cnt<=b[u]-1)
{
g.pop_back();
cnt+=b[c];
int x=u,y=c;
if(x>y)swap(x,y);
ans.insert({x,y});
dfs(c);
}
else break;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
cin>>b[i];
for(int i=n;i>=1;i--)
g.push_back(a[i]);
int k=g.back();g.pop_back();
dfs(k);
for(auto &t:ans)
cout<<t.first<<" "<<t.second<<'\n';
return 0;
}