标签:
?log2S(i,j)?+1 就是S(i,j) 的二进制位数.....
枚举二进制的每一位数,计算相应的权值
具体作法就是对每个二进制位数 i ,扫一遍数组,对每个数 j 维护一个L,R 表示以该数为左端点,右端点可以在L~R的范围,这个区间内的值
加起来有 i 位二进制位数,那么这个数对答案的贡献为 设: dur = (R-L+1) 贡献值: dur*j+(R+L)*dur/2
C++秒T , G++ 1.3s ac
1 2 1 1
12
/* ***********************************************
Author :CKboss
Created Time :2015年08月07日 星期五 16时48分08秒
File Name :HDOJ5358.cpp
************************************************ */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long int LL;
const int maxn=100100;
int n;
LL s[maxn];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T_T;
scanf("%d",&T_T);
while(T_T--)
{
scanf("%d",&n);
for(int i=1,x;i<=n;i++)
{
scanf("%d",&x);
s[i]=s[i-1]+x;
}
LL ans=0;
for(int i=0;i<35;i++)
{
/// 在left 和 right 之间的数有(i+1)个1
LL left=(1LL<<i);
LL right=(1LL<<(i+1LL))-1LL;
if(i==0) left=0LL;
int L=1,R=1;
for(int j=1;j<=n;j++)
{
/// Move L
if(L<j) L=j;
while(L<=n&&s[L]-s[j-1]<left) L++;
if(L==n+1) L--;
if(L==n&&s[L]-s[j-1]<left) break;
if(R<L) R=L;
/// Move R
while(R<=n&&s[R]-s[j-1]<=right) R++;
if(R==n+1) R--;
if(s[R]-s[j-1]>right) R--;
LL dur=R-L+1;
ans=ans+(i+1LL)*(dur*j+(R+L)*dur/2LL);
}
}
cout<<ans<<endl;
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/ck_boss/article/details/47346373