1. 程式人生 > 其它 >Codeforces - 1098C - Construct a tree

Codeforces - 1098C - Construct a tree

Problem - C - Codeforces

 

題意大致為給出n,s,構造節點數為n,所有點的深度之和為s的樹,並且要求分支系數儘可能小,分支系數為兒子個數的最大值

手模樣例發現分支系數k越大,sm(構造方案的深度之和)越小

首先判斷無解就是不在2*n-1(菊花圖)~(n+1)*n/2(鏈)的範圍內

其次由於s關於k的單調性,可以二分k,同一個k,當樹是完全k叉樹時,得到的sm最小,二分出使sm<=s的最小k

然後考慮在這個完全二叉樹的基礎上變成最終答案

維護每層的最右側的節點,這是一條鏈,把v放到這條鏈的u上,且dep(u)>=dep(v),則能使sm變成sm+dep(u)-dep(v)+1

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define int long long
 5 const int MAXN=1e5+17;
 6 int n;LL s;
 7 vector<int >v[MAXN];
 8 int p[MAXN],tot;
 9 int mxdep;
10 LL lres=0;
11 inline bool check(int x){
12     for(int i=1;i<=n;++i)v[i].clear();
13 int tmp=n-1; 14 LL res=1,base=2; 15 v[1].clear(); 16 v[1].push_back(1); 17 p[tot=1]=0; 18 while(tmp){ 19 v[base].clear(); 20 for(int j=0;tmp&&j<v[base-1].size();++j){ 21 int y=v[base-1][j]; 22 for(int k=0;tmp&&k<x;++k)
23 p[++tot]=y,tmp--,res+=base,v[base].push_back(tot); 24 } 25 base++; 26 } 27 mxdep=base-1; 28 lres=res; 29 return res<=s; 30 } 31 signed main(){ 32 scanf("%lld%lld",&n,&s); 33 if(s<2LL*n-1||s>(n+1LL)*n/2LL)puts("No"),exit(0); 34 puts("Yes"); 35 int l=1,r=n-1; 36 while(r-l>1){ 37 int mid=l+r>>1; 38 if(check(mid))r=mid; 39 else l=mid; 40 } 41 int ans=0; 42 if(check(l))ans=l; 43 else check(r),ans=r; 44 // cout<<ans<<endl; 45 46 47 int js=s-lres; 48 for(int i=mxdep;js&&i>1;--i){ 49 for(int j=v[i].size()-1;js&&j>0;--j){ 50 int pp=i,y=v[i][j]; 51 v[i].pop_back(); 52 if(js-(mxdep-i+1)>=0)pp=mxdep; 53 else pp=js+i-1; 54 p[y]=v[pp][0]; 55 v[pp+1].push_back(y); 56 mxdep=max(mxdep,pp+1); 57 js-=(pp-i+1); 58 } 59 } 60 61 for(int i=2;i<=n;++i)printf("%lld%c",p[i],i==n?'\n':' '); 62 return 0; 63 } 64 /* 65 66 71 1329 67 68 */
View Code