"華為杯" 武漢大學21級新生程式設計競賽
阿新 • • 發佈:2022-04-05
比賽連結
"華為杯" 武漢大學21級新生程式設計競賽
D.和諧之樹
求對區間 \([1, n]\) 建立線段樹後最大節點編號
解題思路
dfs
顯然,構建的線段樹為一棵完全二叉樹,答案肯定位於深度最深且最靠右的節點上,考慮左右子樹的深度,如果左子樹深度大於右子樹則排除右子樹,否則排除左子樹。注意,這裡求深度由於遞迴求解的複雜度過高,需要迭代求,即每次轉到長度較大的一半直到為 \(1\) 即得深度
- 時間複雜度:\(O(tlogn)\)
程式碼
// Problem: 和諧之樹 // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/31620/D // Memory Limit: 524288 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } int t; LL n,res; int deep(LL n) { int res=0; while(n>1) { n=(n+1)/2; res++; } return res; } void dfs(LL x,LL id) { res=max(res,id); if(x==1)return ; if(deep((1+x)/2)>deep(x-(1+x)/2))dfs((1+x)/2,id<<1); else dfs(x-(1+x)/2,id<<1|1); } int main() { for(scanf("%d",&t);t;t--) { scanf("%lld",&n); res=0; dfs(n,1); printf("%lld\n",res); } return 0; }