迫真小游戏



给定一棵树,每个结点有值 ,确定一个字典序最小的排列,保证在 号结点之前每个 的深度要小于等于 .



以最小的 开始找,查找深度小于等于 且结点标号最小的值,用线段树维护即可.


#include<bits/stdc++.h>
#define sc scanf
using namespace std;
const int N=6e5+5;
const int mod=1e9+7;
const int oo=1e9+7;
typedef unsigned long long ull;
typedef long long ll;
template <typename it>int o(it a){cout<<a<<endl;return 0;}
int MIN[N<<2|1];
priority_queue<int,vector<int>,greater<int> >q[N];
void build(int l,int r,int rt){
    if(l==r){
        if(l==1)MIN[rt]=oo;
        else MIN[rt]=q[l].top();
        return;
    }
    int mid=l+r>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    MIN[rt]=min(MIN[rt<<1],MIN[rt<<1|1]);
}
void up(int l,int r,int rt,int pos,int val){
    if(l==r&&l==pos){
        MIN[rt]=val;
        return;
    }
    int mid=l+r>>1;
    if(pos<=mid)up(l,mid,rt<<1,pos,val);
    else up(mid+1,r,rt<<1|1,pos,val);
    MIN[rt]=min(MIN[rt<<1],MIN[rt<<1|1]);
}
int Q(int l,int r,int rt,int R){
    if(r<=R)return MIN[rt];
    int mid=l+r>>1;
    int ans=oo;
    if(R>mid)ans=min(ans,Q(mid+1,r,rt<<1|1,R));
    ans=min(ans,Q(l,mid,rt<<1,R));
    return ans;
}
int n,a[N],depth=0;
struct edge{
    int u,v,next;
}g[N<<1];
int tot=0;
int head[N];
int ans[N],pos[N];
set<int>p;
int dep[N],s[N],b[N];
void add(int u,int v){
    g[++tot]={u,v,head[u]};
    head[u]=tot;
}
void dfs(int u,int fa){
    dep[u]=dep[fa]+1;
    depth=max(depth,dep[u]);
    for(int i=head[u];~i;i=g[i].next)if(g[i].v^fa)dfs(g[i].v,u);
}
int main(){
    //freopen("in.txt","r",stdin);
    memset(head,-1,sizeof(head));
    cin>>n;
    for(int i=1;i<n;i++){
        int u,v;
        sc("%d%d",&u,&v);
        add(u,v),add(v,u);
    }
    dfs(1,0);
    sc("%*d");ans[1]=1;int t=1;
    for(int i=2;i<=n;i++){sc("%d",&a[i]);if(a[i]>=depth)a[i]=depth;s[a[i]]++;p.insert(a[i]);}
    for(int i=2;i<=n;i++)q[dep[i]].push(i),pos[i]=dep[i];
    build(1,depth,1);
    while(t<=n){
        if(t==n)break;
        int val=*p.begin();
        int mi=Q(1,depth,1,val);
        if(mi==oo)break;
        ans[++t]=mi;
        q[pos[mi]].pop();
        if(q[pos[mi]].empty())
        up(1,depth,1,pos[mi],oo);
        else up(1,depth,1,pos[mi],q[pos[mi]].top());
        s[a[mi]]--;
        if(s[a[mi]]==0)p.erase(a[mi]);
    }
    for(int i=1;i<=n;i++)printf("%d%c",ans[i]," \n"[i==n]);
}