HDU 5764 After a Sleepless Night

来源:互联网 发布:阿里云服务器禁止ping 编辑:程序博客网 时间:2024/06/05 02:09

给定一棵有根树,点权为1~n的全排列,已知每个点子树中权值的最大值(不妨称为新值),求字典序最小的点权方案。

原题开始没有给出根的位置,然而被秒了ASC 24E(Andrew Stankevich Contest 24 E)的bblss123一眼识破:显然是新值为n的链的两端嘛。

ASC 24E(Translate By rzz):
对于一个1~n的排列a,定于a/i为在该排列中去掉i后,剩下的树相对大小和位置不变构成一个1~n-1的排列。如(1,3,5,2,6,4)/2=(1,2,4,5,3)。所有1≤i≤n打乱顺序后给出,要求还原一个合法的排列a。

官方题解:
可以发现,无论选哪个做根,不影响其它链的上下方向及链之间的相对关系,即不影响合法性。因为没选的那一头一定填n,所以我们贪心地选择id小的端点做根(否则交换两个端点的值,将得到更优的答案)。

剩下的就比较随意了,欢迎回复这题该放什么分类。

#include<set>#include<ctime>#include<queue>#include<cstdio>#include<bitset>#include<cctype>#include<bitset>#include<cstdlib>#include<cassert>#include<cstring>#include<iostream>#include<algorithm>#define inf (1<<30)#define INF (1ll<<62)#define fi first#define se second#define rep(x,s,t) for(int x=s,t_=t;x<t_;x++)#define per(x,s,t) for(int x=t-1,s_=s;x>=s_;x--)#define prt(x) cout<<#x<<":"<<x<<" "#define prtn(x) cout<<#x<<":"<<x<<endl#define pc(x) putchar(x)#define pb(x) push_back(x)#define hash asfmaljkg#define rank asfjhgskjf#define y1 asggnja#define y2 slfvmusing namespace std;typedef long long ll;typedef pair<int,int> ii;template<class T>void sc(T &x){    int f=1;char c;x=0;    while(c=getchar(),c<48)if(c=='-')f=-1;    do x=x*10+(c^48);    while(c=getchar(),c>47);    x*=f;}template<class T>void nt(T x){    if(!x)return;    nt(x/10);    pc(x%10+'0');}template<class T>void pt(T x){    if(x<0)pc('-'),x=-x;    if(!x)pc('0');    else nt(x);}template<class T>void ptn(T x){    pt(x);putchar('\n');}template<class T>void pts(T x){    pt(x);putchar(' ');}template<class T>inline void Max(T &x,T y){if(x<y)x=y;}template<class T>inline void Min(T &x,T y){if(x>y)x=y;}const int maxn=100005;int n,a[maxn];int last[maxn],ecnt;struct Edge{    int to,nxt;}e[maxn<<1];void ins(int u,int v){    e[ecnt]=(Edge){v,last[u]};    last[u]=ecnt++;}int getRT(int x,int f){    for(int i=last[x];i!=-1;i=e[i].nxt){        int to=e[i].to;        if(to==f)continue;        if(a[to]==n)return getRT(to,x);    }    return x;}bool ok;int mark[maxn],allc;int val[maxn];void dfs(int x,int f){    int repeat=0;    for(int i=last[x];i!=-1;i=e[i].nxt){        int to=e[i].to;        if(to==f)continue;        if(a[x]==a[to])repeat++;        if(a[x]<a[to])ok=false;        else dfs(to,x);    }    if(!repeat){        val[x]=a[x];        mark[a[x]]=allc;    }    if(repeat>1)ok=false;}struct unit{    int id,lim;    bool operator<(const unit &a)const{        return lim>a.lim;    }}d[maxn];bool chk(int RT){    ok=true;    ++allc;    memset(val,0,n+1<<2);    dfs(RT,0);    if(!ok)return false;    int top=1;    priority_queue<int>q;    for(int i=n;i>=1;i--){        if(mark[i]==allc)continue;        while(top<=n&&d[top].lim>=i){            q.push(d[top].id);            top++;        }        while(!q.empty()){            int p=q.top();            if(val[p])q.pop();            else break;        }        if(q.empty())return false;        int p=q.top();q.pop();        val[p]=i;    }    return true;}void solve(){    sc(n);    memset(last,-1,n+1<<2);    ecnt=0;    rep(i,1,n+1)sc(a[i]);    int u,v;    rep(i,1,n){        sc(u);sc(v);        ins(u,v);        ins(v,u);    }    int RT=-1;    rep(i,1,n+1){        if(a[i]==n){            RT=i;            break;        }    }    if(RT==-1){        puts("Impossible");        return;    }    rep(i,1,n+1)        d[i]=(unit){i,a[i]};    sort(d+1,d+n+1);    RT=getRT(RT,0);    RT=min(RT,getRT(RT,0));    if(!chk(RT)){        puts("Impossible");        return;    }    rep(i,1,n+1){        if(i==n)ptn(val[i]);        else pts(val[i]);    }}int main(){//  freopen("pro.in","r",stdin);//  freopen("chk.out","w",stdout);    int cas,kase=0;    sc(cas);    while(cas--){        printf("Case #%d: ",++kase);        solve();    }    return 0;}
0 0
原创粉丝点击