dfs序列+启发式合并+树状数组
class Solution {
public:
const static int N=1e5+5;
int tree[N];
int get_lowbit(int i){
return i&(-i);
}
void add(int i,int v){
while(i<N){
tree[i]+=v;
i+=get_lowbit(i);
}
}
int ask(int i){
int ans = 0;
while(i){
ans+=tree[i];
i -= get_lowbit(i);
}
return ans;
}
int cntGen[N];
int cnt=1;
int h[N], nx[N], e[N];
int gen[N];
void add_edge(int a,int b){
e[cnt] = b, nx[cnt] = h[a], h[a] = cnt++;
}
int big[N];
int son[N];
int in[N], out[N], Node[N];
int time1 = 0;
void dfs0(int u){
son[u] = 1;
in[u] = ++time1;
Node[time1] = u;
for(int i=h[u];i;i=nx[i]){
int t = e[i];
dfs0(t);
son[u] += son[t];
if(!big[u] || son[big[u]]<son[t]){
big[u] = t;
}
}
out[u] = time1;
}
void add_tree(int i){
if(!cntGen[i]){
add(i,1);
}
cntGen[i]++;
}
void del_tree(int i){
cntGen[i]--;
if(cntGen[i]==0){
add(i,-1);
}
}
int ans[N];
int mx_gen = 0;
void dfs1(int u, bool keep){
for(int i=h[u];i;i=nx[i]){
int t= e[i];
if(t!=big[u]){
dfs1(t, false);
}
}
if(big[u]){
dfs1(big[u], true);
}
for(int i=h[u];i;i=nx[i]){
int t = e[i];
if(t!=big[u]){
for(int j=in[t];j<=out[t];j++){
int v = Node[j];
add_tree(gen[v]);
}
}
}
add_tree(gen[u]);
int l=1, r=mx_gen;
while(l<=r){
int mid = (l+r)>>1;
if(ask(mid)==mid){
l = mid+1;
}else{
r = mid-1;
}
}
ans[u] = r;
if(!keep){
for(int i=in[u];i<=out[u];i++){
del_tree(gen[Node[i]]);
}
}
}
vector<int> smallestMissingValueSubtree(vector<int>& parents, vector<int>& nums) {
memset(cntGen, 0, sizeof cntGen);
memset(tree,0,sizeof tree);
memset(big, 0, sizeof big);
memset(son, 0, sizeof son);
for(int i=0;i<parents.size();i++){
if(parents[i]!=-1){
add_edge(parents[i], i);
}
}
for(int i=0;i<nums.size();i++){
gen[i] = nums[i];
mx_gen = max(mx_gen, gen[i]+1);
}
dfs0(0);
dfs1(0,0);
vector<int>res;
for(int i=0;i<nums.size();i++){
res.push_back(ans[i]+1);
}
return res;
}
};