zoukankan      html  css  js  c++  java
  • HDU 5358 多校第6场 First One

    First One

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
    Total Submission(s): 672    Accepted Submission(s): 193


    Problem Description
    soda has an integer array a1,a2,,an. Let S(i,j) be the sum of ai,ai+1,,aj. Now soda wants to know the value below:
    i=1nj=in(log2S(i,j)+1)×(i+j)

    Note: In this problem, you can consider log20 as 0.
     

    Input
    There 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 n (1n105), the number of integers in the array.
    The next line contains n integers a1,a2,,an (0ai105).
     

    Output
    For each test case, output the value.
     

    Sample Input
    1 2 1 1
     

    Sample Output
    12
     

    Source


    首先题意不是啥问题,就是给你个数组,让你求那个式子,s表示i到j的和。

    比赛的时候想了个带二分的,就是统计log2可能出现的可能,一共同拥有34种,然后求一个前缀和,前缀和是递增的,能够二分。就写了

    复杂度没算好,以为33*n*log(n)能过。结果跪了一下午,昨天就这么愉快的跪了

    赛后题解上说用俩指针扫一遍,不得不吐槽一下。MD题解都是英文的。

    联想到一次bestcoder 有一个题是求一共序列中两个数的和模上一个数最大,我以前的做法就是排序二分。而正解就是俩指针扫一遍,然而我没有记住

    这个题就卡这个log(n)然而我就是过不去,诶。还是思维被限制住了

    今天上午搞了个33 * n的

    思路:

    把数组处理成 前缀和,把log分类,有35种情况,题中吧log(0) 规为0。须要特判,题中给的最大的sum值为10^10,所以有35种情况,

    那么就分情况讨论,一层循环。里面就是枚举n。然后找到两个值一个是sum[i-1] + 2^j的位置。另一个是sum[i-1]+2^(j+1)的位置,这段区间内的log值就全为j,用等差数列求和公式就能瞬间算出来这段区间的值,并且仅仅须要两个标记扫一遍。为何能够仅仅扫一遍呢,sum数组的值是递增的。须要找的值也是递增的。所下面次找的时候仅仅须要在上次寻找的后面继续接上就OK

    /****************************************
    ** 2015 Multi-University Training Contest 6
    ** 1006 First One
    ** HDU 5358
    ** by calamity_coming
    **************************************/
    
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MAX_LONG = 1E5;
    ll   a[MAX_LONG + 10];
    ll sum[MAX_LONG + 10];
    ll cf2[40];
    
    void init()
    {
        ll k = 1;
        for(int i=0; i<=34; ++i)
        {
            cf2[i] = (k<<(i));
        }
    }
    int main()
    {
        init();
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n;
            scanf("%d",&n);
            sum[0] = 0;
            for(int i=1; i<=n; ++i)
            {
                scanf("%I64d",&a[i]);
                sum[i] = sum[i-1] + a[i];//前缀和处理
            }
            sum[n+1] = 1E17;
            ll ans = 0;
    
            //0
            for(int i=1; i<=n; ++i)//0比較特殊。要特殊的干
            {
                int p = i;
                while(sum[p]==sum[i-1] && p<=n+1)
                {
                    ++p;
                }
                --p;
                if(p>=i)
                {
                    ans += (ll)(i*3+p)*(ll)(p-i+1)/2;
                }
            }
    
            for(int j=0; j<=33; ++j)//这是每一个情况
            {
                int p1 = 0,p2 = 0;//用两个指针扫一遍
                for(int i=1; i<=n; ++i)//当i递增时,新的p1,p2一定在后面
                {
                    ll adc = sum[i-1] + cf2[j];
                    while(sum[p1]<adc && p1<=n)
                    {
                        ++p1;
                    }
                    adc = sum[i-1] +cf2[j+1];
                    while(sum[p2]<adc && p2<=n+1)
                    {
                        ++p2;
                    }
                    --p2;
                    if(p2>=p1 && p2)
                    {
                        ans += (j+1)*(ll)(i*2+p1+p2)*(ll)(p2-p1+1)/2;
                    }
                }
            }
            printf("%I64d
    ",ans);
        }
        return 0;
    }
    




  • 相关阅读:
    如何在Nginx下配置PHP程序环境
    Nginx服务器不支持PATH_INFO的问题及解决办法
    php内置函数分析之str_pad()
    php常用几种设计模式的应用场景
    func_get_args()在php71与php56的区别
    Restful api 防止重复提交
    Game-Tech小游戏专场第二趴,这次帝都见
    入门系列之在Ubuntu上使用MySQL设置远程数据库优化站点性能
    入门系列之在Ubuntu上使用Netdata设置实时性能监控
    叶聪:朋友圈背后的计算机视觉技术与应用
  • 原文地址:https://www.cnblogs.com/yfceshi/p/6905876.html
Copyright © 2011-2022 走看看