2015多校第6场 HDU 5358 First One 枚举,双指针
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5358
题意:如题。
解法:观察式子发现,由于log函数的存在,使得这个函数的值域<=34,然后我们枚举这个值域,对于这个值域,我们用双指针O(n)维护值前缀和在这个值域里面的区间,计算即可。
#include <bits/stdc++.h> using namespace std; const int maxn = 100005; typedef long long LL; LL l[35], r[35], sum[maxn]; LL a, b, num, ans; int main() { l[0] = 0; r[0] = 1; for(int i=1; i<=34; i++){ l[i] = (1LL<<i); r[i] = ((1LL<<(i+1))-1LL); } int T, n; scanf("%d", &T); while(T--) { scanf("%d", &n); memset(sum, 0, sizeof(sum)); for(int i=1; i<=n; i++){ int x; scanf("%d", &x); sum[i] = sum[i-1]+x; } ans = 0; for(int i=1; i<35; i++){ if(sum[n]<l[i-1]) break; a = 1, b = 0; num = 0; for(LL j=1; j<=n; j++){ a = max(a, j); while(a<=n&&sum[a]-sum[j-1]<l[i-1]) a++; b = max(b, a-1); while(b+1<=n&&sum[b+1]-sum[j-1]>=l[i-1]&&sum[b+1]-sum[j-1]<=r[i-1]) b++; if(a<=b) num += (b-a+1)*j+(b+a)*(b-a+1)/2; } ans += num*i; } printf("%lld\n", ans); } return 0; }