1. 程式人生 > 其它 >"華為杯" 武漢大學21級新生程式設計競賽

"華為杯" 武漢大學21級新生程式設計競賽

比賽連結

"華為杯" 武漢大學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;
}