Task
給出一棵n個結點的有根樹,結點用正整數1~n編號。
每個結點有一個1~n的正整數權值,不同結點的權值不相同,
並且一個結點的權值一定比它父結點的權值大(根結點的權值最大,一定是n)。現在有些結點的權值是已知的,並且如果一個結點的權值已知,它父結點的權值也一定已知。
問還有哪些結點的權值能夠唯一確定。
n<=1,000,000, 1<=pi<=n, 0<=zi<=n.
Solution
根據樹的結構,我們可以對每個沒有確定大小的點i列出一個不等式:
那麼只要按照
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
const int M=1e6+5;
int mark[M],rt,ec=0,head[M],n,A[M],Bit[M],C[M],dep[M],tot=0,m=0;
struct node{
int to,nex;
bool operator<(const node &tmp)const{
return nex<tmp.nex;
}
}e[M<<1],B[M];
inline void rd(int &res){
res=0;char c;
while(c=getchar(),c<48);
do res=(res<<1)+(res<<3)+(c^48);
while(c=getchar(),c>=48);
}
inline void print(int k){
if(!k)return;
print(k/10);
putchar(k%10^48);
}
inline void sc(int k){
if(k<0){k=-k;putchar('-');}
print(k);
if(k==0)putchar('0');
putchar('\n');
}
void ins(int a,int b){
e[ec]=(node){a,head[b]};
head[b]=ec++;
e[ec]=(node){b,head[a]};
head[a]=ec++;
}
void dfs(int x,int f,int a,int d){//a
dep[x]=d;
if(A[x])a=A[x];
else{
B[++tot]=(node){x,upper_bound(C,C+m,a-1)-C-1};
a=C[B[tot].nex];
}
for(int i=head[x];~i;i=e[i].nex){
int y=e[i].to;
if(y==f)continue;
dfs(y,x,a,d+1);
}
}
int main(){
int a,b,i,j,k;
rd(n);
memset(head,-1,sizeof(head));
for(i=1;i<=n;i++){
rd(a);rd(A[i]);
if(A[i])mark[A[i]]=1;
if(i!=a)ins(i,a);
else rt=i;
}
A[rt]=n;
mark[n]=rt;
for(i=1;i<=n;i++){
if(!mark[i])C[m++]=i;//還可選的數字
}
dfs(rt,rt,rt,1);
sort(B+1,B+1+tot);
sort(C,C+m);
k=0;
for(i=1;i<=tot;i=j){
j=i;
while(j<=n&&B[j].nex==B[i].nex)j++;
if(j-i==1){//B[j].nex就是最後大於的數字
if(B[i].nex==k)A[B[i].to]=C[k++];
else k++;
}
else{
k+=j-i;//
}
}
for(i=1;i<=n;i++)sc(A[i]);
return 0;
}