构造——cf1311E好题
/* 对于每个n,满足条件的d总是在一段区间内 d的最小值就是完全二叉树的dmin,最大值是链的dmax [dmin,dmax]这段区间内的所有值都可以取到 策略:先构造一棵n个点的完全二叉树,自底层向上判断,每次只把一个可以往下挪的点往下挪 这样每次d只会+1 */ #include<bits/stdc++.h> using namespace std; #define N 5005 int num[N],h; int main(){ int t;cin>>t; while(t--){ h=0; memset(num,0,sizeof num); int n,d; cin>>n>>d; int dmin=0,dmax=0; int tmp=n; while(tmp){ h++; if(tmp>=(1<<(h-1))){ tmp-=(1<<(h-1)); dmin+=(1<<(h-1))*(h-1); num[h]=(1<<(h-1)); }else { dmin+=tmp*(h-1); num[h]=tmp; tmp=0; } } for(int i=1;i<=n;i++)dmax+=i-1; if(d<dmin || d>dmax){puts("NO");continue;} d-=dmin; while(d){ d--; for(int i=h+1;i>=2;i--){ if(num[i]+1<=2*(num[i-1]-1)){ num[i]++; num[i-1]--; if(i==h+1)h=i; break; } } } puts("YES"); int now=1; for(int i=2;i<=h;i++){ for(int j=1;j<=num[i];j++) cout<<now+(j+1)/2-1<<" "; now+=num[i-1]; } puts(""); } }
/* 对于每个n,满足条件的d总是在一段区间内 d的最小值就是完全二叉树的dmin,最大值是链的dmax [dmin,dmax]这段区间内的所有值都可以取到 策略:先构造一棵n个点的完全二叉树,自底层向上判断,每次只把一个可以往下挪的点往下挪 这样每次d只会+1 */ #include<bits/stdc++.h> using namespace std; #define N 5005 int num[N],h; int main(){ int t;cin>>t; while(t--){ h=0; memset(num,0,sizeof num); int n,d; cin>>n>>d; int dmin=0,dmax=0; int tmp=n; while(tmp){ h++; if(tmp>=(1<<(h-1))){ tmp-=(1<<(h-1)); dmin+=(1<<(h-1))*(h-1); num[h]=(1<<(h-1)); }else { dmin+=tmp*(h-1); num[h]=tmp; tmp=0; } } for(int i=1;i<=n;i++)dmax+=i-1; if(d<dmin || d>dmax){puts("NO");continue;} d-=dmin; while(d){ d--; for(int i=h+1;i>=2;i--){ if(num[i]+1<=2*(num[i-1]-1)){ num[i]++; num[i-1]--; if(i==h+1)h=i; break; } } } puts("YES"); int now=1; for(int i=2;i<=h;i++){ for(int j=1;j<=num[i];j++) cout<<now+(j+1)/2-1<<" "; now+=num[i-1]; } puts(""); } }