【CodeForce 1286B】 Numbers on Tree

2000分的構造,看了題解才發現如何構造,發現是個構造好題

題意:

給出一棵樹,樹上每個節點有權值a,屬性c,代表c的子樹上小於其權值的點的個數

現在給出 樹的結構及各節點c的值

問是否能成功分配a的值使得題意滿足條件

題目思路:

首先不得不說...賊秀

首先判斷 是否可以構造出來,也就是說 c是否大於等於子樹節點數

如果可以構造出來,那麼存在一個結論:將樹的各節點 分配一下 1~n的全排列,那麼一定存在一種可行方案。

既然知道可行那麼就直接構造就好了

爲了確保 下面不會再次影響到上面

我們從頂點更新,假設當前節點c爲2,我們就從1~n中還沒有選的第c+1大賦值,那麼接下來他的子樹中一定有小於c+1的值,也就是存在c個小於他的節點

構造完成:

Code:

/*** keep hungry and calm CoolGuang!***/
//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18;
const int maxn=2e5+6;
const int mod=1e9+7;
const double eps=1e-9;
inline bool read(ll &num)
{char in;bool IsN=false;
in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m;
int root;
int sz[maxn];
int tot=0;
vector<int>v[maxn];
int p[maxn];
int vis[maxn];
int res[maxn];
int cnt=0;
int f=0;
void dfs(int u){
    sz[u]=1;
    int cot=0;
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            cot++;
            if(cot==p[u]+1){
                vis[i]=1;
                res[u]=i;
                break;
            }
        }
    }
    for(int e:v[u]){
        dfs(e);
        sz[u]+=sz[e];
    }
    if(p[u]>=sz[u]) f=1;
}
int main(){
    read(n);
    for(int i=1;i<=n;i++){
        int x;scanf("%d%d",&x,&p[i]);
        if(x) v[x].push_back(i);
        else root=i;
    }
    dfs(root);
    if(!f){
        printf("YES\n");
        for(int i=1;i<=n;i++)
            printf("%d ",res[i]);
    }
    else printf("NO\n");
    return 0;
}
/**
 
4 7 8 6
6
 
1 2 3 3  3 3
2 4 2 4  5 5
 
2+6+11+6+2
**/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章