80 pts 求助
  • 板块P9689 Bina.
  • 楼主zct_sky
  • 当前回复5
  • 已保存回复5
  • 发布时间2023/10/3 09:48
  • 上次更新2023/11/2 16:23:44
查看原帖
80 pts 求助
519734
zct_sky楼主2023/10/3 09:48

WA 最后一个点。

大体思路:

m=0m = 0 和 m≠0m \ne 0 时分别讨论。

m≠0m \ne 0 时,由于除了最后一层,其他层节点都是满的,因此可以先删最后一层之后一层层删,直至超过 mm 或输出 −1-1。

m=0m = 0 时,若该树本身即为满二叉树,直接计算答案,否则先算满二叉树部分,再用分治计算最后一次剩余节点编号之和后计算答案即可。

代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline ll read(){
	ll x=0,y=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')y=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch&15),ch=getchar();
	return x*y;

}
int t;
ll n,m,ans;
ll f(ll a,ll b){
	if(b<=1||a==1)return 0;
	if(a==2)return 1;
	if(a==b)return (a-1)*a/2;
	if(b>a/2)return 2*f(a/2,a/2)+2*f(a/2,b-a/2)+b-a/2;
	return 2*f(a/2,b);
}
int main(){
	t=read();
	while(t--){
		n=read();m=read();
		ll k=1,d=1;
		while(k*2<=n)d++,k=k*2;
		if(m){
			ll t=(n-k)*2;
			m-=t;
			if(m<=0){
				ans=k*(2*k-1)/d;
			}else{
				while(m>0&&k>1){
					t=k;
					m-=t;
					k/=2;
					d--;
				}
				if(m>0)ans=-1;
				else ans=k*(2*k-1)/d;
			}
		}else{
			if(n==k){
				ans=k*(2*k-1)/d;
			}else{
				d++;
				ll fuck=1ll*(f(k,n-k)+k*(n-k))*4+n-k;
				ans=(ll)(k*(2*k-1)+fuck)/d;
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}

和 官方题解 对拍了一下发现了一个 WA 的数据:

2
16 0
17 0

官方题解:

99
99

我的输出:

99
93

求调。

2023/10/3 09:48
加载中...