HDU 5358 枚举+尺选
Posted kongbb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5358 枚举+尺选相关的知识,希望对你有一定的参考价值。
soda has an integer array a1,a2,…,ana1,a2,…,an. Let S(i,j)S(i,j) be the sum of ai,ai+1,…,ajai,ai+1,…,aj. Now soda wants to know the value below:
∑i=1n∑j=in(⌊log2S(i,j)⌋+1)×(i+j)
Note: In this problem, you can consider log20 as 0.
InputThere are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains an integer nn (1≤n≤105), the number of integers in the array.
The next line contains nn integers a1,a2,…,an(0≤ai≤105).OutputFor each test case, output the value.Sample Input
1 2 1 1
Sample Output
12
题意:求一个数组对题目中出现的那个公式的值
做过好几道枚举的题了,但是遇到题还是想不出来使用枚举。
根据题目给的数据范围,我们知道sum(1,n)<=1e10 floor(log2(1e10)) = 33
所以我们枚举log2(sum+1)的值,进行尺选就可以了。
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int maxn = 1e5+5; ll s[maxn]; ll low[50], high[50]; int n, x; ll solve(int k){ if(s[n]<low[k-1])return 0; ll l=1, r=1,num=0; for(ll j=1;j<=n;j++){ l = max(l,j); while(l<=n && s[l]-s[j-1]<low[k-1])l++; r = max(r,l); while(r<=n && s[r]-s[j-1]<=high[k-1])r++; if(r>l) num += (r-l)*j+(l+r-1)*(r-l)/2; } return num*k; } int main(){ int t; scanf("%d",&t); for(int i=1;i<35;i++){ low[i] = 1ll<<i; high[i] = (1ll<<(i+1))-1; } low[0]=0,high[0]=1; while(t--){ ll ans = 0; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&x),s[i] = s[i-1]+x; for(int i=1;i<35;i++) ans += solve(i); printf("%lld\n",ans); } return 0; }
以上是关于HDU 5358 枚举+尺选的主要内容,如果未能解决你的问题,请参考以下文章