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.
扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄
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
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。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; }View Code

更多精彩