hdu 5358 First One [枚举+尺取法]

本文介绍了一种针对特定求和式问题的优化算法。通过利用log2特性与尺取法,该算法能在O(n log n)的时间复杂度内解决枚举区间问题。文章提供了详细的AC代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给你n个数,求他给出的求和式

题解:由于求和式中含有log2,当我们枚举左端点的时候,右端点在一定范围内log2值是不会变的,所以我们可以对每一种log2的取值做枚举,然后枚举每一个左端点,再找到右端点符合条件的范围,但是假如用二分查找右端点得到结果时间复杂度n*logsum*logn,TLE,所以可以考虑用尺取法,所以总的复杂度为n*logn。

AC代码:

#include<stdio.h>
#include<math.h>
typedef long long ll;
ll a[100005],sum[100005];
ll cf2[40];  
void init() 
{ 
	ll k = 1; 
	for(int i=0; i<=34; ++i) 
	{ 
		cf2[i] = (k<<(i)); 
	} 
} 
int main()
{
	init();
	ll T;
	scanf("%lld",&T);
	while(T--)
	{
		ll n;
		scanf("%lld",&n);
		for(ll i=1;i<=n;i++)
		{
			scanf("%lld",&a[i]);
			sum[i]=sum[i-1]+a[i];
		}
		sum[n+1]=(ll)1E17;
		ll ans=0,gg;
		for(int i=1;i<=n;++i)
		{ 
			int p=i; 
			while(sum[p]==sum[i-1]&&p<=n+1)++p; 
			--p; 
			if(p>=i)ans+=(ll)(i*3+p)*(ll)(p-i+1)/2; 
		}
		ll now=1;
		ll last=0;
		for(int j=0;j<=33;j++)
		{ 
			int p1=0,p2=0;
			for(int i=1; i<=n; ++i)
			{ 
				ll adc = sum[i-1] + cf2[j]; 
				while(sum[p1]<adc && p1<=n)++p1; 
				adc = sum[i-1] +cf2[j+1]; 
				while(sum[p2]<adc && p2<=n+1)++p2;
				--p2; 
				if(p2>=p1&&p2)ans+=(j+1)*(ll)(i*2+p1+p2)*(ll)(p2-p1+1)/2;
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值