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 .
Let  be
the sum of .
Now soda wants to know the value below:

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

Input

There are multiple test cases. The first line of input contains an integer ,
indicating the number of test cases. For each test case:

The first line contains an integer  ,
the number of integers in the array.

The next line contains  integers  .

Output

For each test case, output the value.

Sample Input

1
2
1 1

Sample Output

12

Source

2015 Multi-University Training Contest 6

首先题意不是啥问题,就是给你个数组,让你求那个式子,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\n",ans);
    }
    return 0;
}
时间: 2024-10-02 20:50:46

HDU 5358 多校第6场 First One的相关文章

HDU 5335 多校第4场 1009 Walk Out

Walk Out Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1794    Accepted Submission(s): 340 Problem Description In an n?m maze, the right-bottom corner is the exit (position (n,m) is the exit)

hdu 5317 多校第三场

开始题意读错了   shit    wa了好久    仔细一看真是水题一枚: 根据素数打表很容易得出每个数的F()值     从而可以看出1到1000000  F()的值最大为7  及(2*3*5*7*11*13*17)   告诉你区间    只需要在这个区间里找到这7个数分辨出先了多少次  这里用一个二维的数组leap[i][j](j小于等于7) 表示i之前j出现的次数    这样就很容易求出区间j的值    纪录在record数组里    就可以求GCD了  这里 我是直接把所有情况列出来了

hdu 2018 多校 第五场

1002 小洛洛 开场挂了N发插入排序的我( 最后还是要靠小洛洛写暴力 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cmath> 5 #include <cstdlib> 6 #include <algorithm> 7 using namespace std; 8 9 const int N = 12; 10 11 int mi

HDU暑假多校第八场J-Taotao Picks Apples

一.题意 给定一个序列,之后给出若干个修改,修改的内容为在原序列的基础上,将某一位元素的值改成给定的值<每次修改相互独立,不保存修改后的结果>.之后询问,在选择第一位元素的情况下,最长递增子序列的长度是多少. 二.题解 考虑不经修改的情况,应当设dp[i]为选取当前位情况下的最长递增子串的长度.则对于这道题,应当认为对于修改a为b,设l_pos为a左边最大的元素的位置,r_pos为a右边大于max(b,r_pos)的元素的位置.则有ans = dp[1] - dp[l_pos] + 1 + d

2014多校第十场1004 || HDU 4974 A simple water problem

题目链接 题意 : n支队伍,每场两个队伍表演,有可能两个队伍都得一分,也可能其中一个队伍一分,也可能都是0分,每个队伍将参加的场次得到的分数加起来,给你每个队伍最终得分,让你计算至少表演了几场. 思路 : ans = max(maxx,(sum+1)/2) :其实想想就可以,如果所有得分中最大值没有和的一半大,那就是队伍中一半一半对打,否则的话最大的那个就都包了. 1 #include <cstdio> 2 #include <cstring> 3 #include <st

多校第六场 HDU 4927 JAVA大数类

题目大意:给定一个长度为n的序列a,每次生成一个新的序列,长度为n-1,新序列b中bi=ai+1?ai,直到序列长度为1.输出最后的数. 思路:这题实在是太晕了,比赛的时候搞了四个小时,从T到WA,唉--对算组合还是不太了解啊,现在对组合算比较什么了-- import java.io.*; import java.math.*; import java.util.*; public class Main { public static void main(String[] args) { Sca

2014 HDU多校弟八场H题 【找规律把】

看了解题报告,发现看不懂 QAQ 比较简单的解释是这样的: 可以先暴力下达标,然后会发现当前数 和 上一个数 的差值是一个 固定值, 而且等于当前数与i(第i个数)的商, 于是没有规律的部分暴力解决,有规律的套公式 //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <cstring&g

2014多校第七场1005 || HDU 4939 Stupid Tower Defense (DP)

题目链接 题意 :长度n单位,从头走到尾,经过每个单位长度需要花费t秒,有三种塔: 红塔 :经过该塔所在单位时,每秒会受到x点伤害. 绿塔 : 经过该塔所在单位之后的每个单位长度时每秒都会经受y点伤害. 蓝塔 : 经过该塔所在单位之后,再走每个单位长度的时候时间会变成t+z. 思路 : 官方题解 : 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define LL long long

HDU 4923 Room and Moor (多校第六场C题) 单调栈

Problem Description PM Room defines a sequence A = {A1, A2,..., AN}, each of which is either 0 or 1. In order to beat him, programmer Moor has to construct another sequence B = {B1, B2,... , BN} of the same length, which satisfies that: Input The inp