BZOJ2799/POI2012 Salaries

Task
給出一棵n個結點的有根樹,結點用正整數1~n編號。
每個結點有一個1~n的正整數權值,不同結點的權值不相同,
並且一個結點的權值一定比它父結點的權值大(根結點的權值最大,一定是n)。現在有些結點的權值是已知的,並且如果一個結點的權值已知,它父結點的權值也一定已知。
問還有哪些結點的權值能夠唯一確定。
n<=1,000,000, 1<=pi<=n, 0<=zi<=n.

Solution
根據樹的結構,我們可以對每個沒有確定大小的點i列出一個不等式:zi<=xi
那麼只要按照xi 從小到大排序,若考慮點i時只有一個數字可選,那麼zi 就是唯一的.假如有k 個點的xi 相同,(當k>1 時,它們的zi 都無法確定)在備選的所有值中把前k 個值刪去即可.

#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;
}

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