【瞎搞】 HDU 5358 First One

来源:互联网 发布:linux mint vs ubuntu 编辑:程序博客网 时间:2024/06/08 19:37

点击打开链接

根据| log2 a +1 | =k    枚举k得到 区间 [2^(k-1), 2^k-1] ;  k =[0,34]

再枚举左端 i: 对于一个i 找到一个区间 [l, r]满足[ 2^(k-1),  2^k-1]

然后就加起来

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <math.h>#include <string>#include <iostream>#include <algorithm>using namespace std;#include <queue>#include <stack>#include <vector>#include <deque>#include <bitset>#include <set>#include <map>typedef long long LL;const int MAXN = 100009;//点数的最大值const int MAXM = 604000;//边数的最大值const LL INF = 1152921504;const LL mod= 1000000007;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int read(){    char ch=' ';    int ans=0;    while(ch<'0' || ch>'9')        ch=getchar();    while(ch<='9' && ch>='0')    {        ans=ans*10+ch-'0';        ch=getchar();    }    return ans;}int a[MAXN],n;LL b[36],sum[MAXN],ans;int gao(LL low,LL top,int k)//[l,r]{    int l=1,r=0;    for(int i=1; i<=n; i++)//star in i    {        if(l<i) l=i;        if(r<i-1) r=i-1;        while(l<=n&&sum[l]-sum[i-1]<low)            l++;        while(r+1<=n&&sum[r+1]-sum[i-1]<=top)            r++;        if(l>r) continue;        if(sum[r]-sum[i-1]<low || sum[r]-sum[i-1]>top) continue;        if(sum[l]-sum[i-1]<low || sum[l]-sum[i-1]>top) continue;        ans+=((LL)(r-l+1)*i+(LL)(l+r)*(r-l+1)/2)*k;    }}int main(){    b[0]=1;    b[1]=2;    for(int i=2; i<=34; i++)        b[i]=b[i-1]*(LL)2;    int t;    scanf("%d",&t);    while(t--)    {        n=read();        sum[0]=0;        for(int i=1; i<=n; i++)        {            a[i]=read();            sum[i]=sum[i-1]+a[i];        }        ans=0;        gao(0,0,1);        for(int i=1; i<=34; i++)        {            gao(b[i-1],b[i]-1,i);        }        printf("%I64d\n",ans);    }    return 0;}/*141 1 1 1*/


0 0
原创粉丝点击