题解:AT_cf17_final_i Full Tournament
xzy_AK_IOI · · 题解
思路分析
考虑比赛的形态,我们可以将其画成一棵分治树,如图:
最上面那排的就是最后的
这个贪心转化到树上就是
那么我们建出图然后套用这个题的解法即可。
时间复杂度为
完整代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define lli long long
#define db long double
#define ull unsigned long long
#define F(i,k,n) for (int i=(k);i<=(n);i++)
#define R(i,k,n) for (int i=k;i>=n;i--)
#define pu push_back
#define mpr make_pair
#define ins insert
#define lowb(x) (x&(-x))
#define mes(a,b) memset(a,b,sizeof a)
const int N=2e6+10;
const int inf=1e18;
const int mod=1e9+7;
struct node{
int id,l,r;
}b[N];
int n;
int l[N],r[N];
int a[N],c[N];
set<int>s;
bool cmp(node a,node b){
if (a.r!=b.r) return a.r<b.r;
return a.l<b.l;
}
int rev(int x){
int y=0;
F(i,0,n-1){
if ((x>>i)&1) y+=(1<<n-1-i);
}
return y;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin>>n;
F(i,0,(1<<n)-1){
cin>>a[i];
if (a[i]) l[i]=r[i]=a[i];
else l[i]=1,r[i]=(1<<n);
}
F(i,0,(1<<n)-1){
F(j,0,n-1){
if ((i>>j)&1){
l[i]=max(l[i],l[i^(1<<j)]+1);
}
}
}
R(i,(1<<n)-1,0){
F(j,0,n-1){
if (!((i>>j)&1)){
r[i]=min(r[i],r[i^(1<<j)]-1);
}
}
}
bool p=1;
F(i,0,(1<<n)) s.insert(i);
F(i,0,(1<<n)-1) b[i+1]={i,l[i],r[i]};
// F(i,0,(1<<n)-1) cout<<l[i]<<' '<<r[i]<<'\n';
sort(b+1,b+1+(1<<n),cmp);
F(i,1,(1<<n)){
int x=*s.lower_bound(b[i].l);
if (x>b[i].r){
cout<<"NO";
return 0;
}
c[b[i].id]=x;
s.erase(x);
}
cout<<"YES\n";
F(i,0,(1<<n)-1){
cout<<c[rev(i)]<<' ';
}
return 0;
}