一维前缀和

大部分的题其实都是一维前缀和

我们先来看一下一维前缀和的公式:sum[i] = sum[i - 1] + a[i]

记住这个就够够的了。

前缀和的主要用途就是降低时间复杂度,比如一道题中数据范围n是十的五次方,那么遍历两层循环必然会超时,此时前缀和就是一种做法。

 

我们来看这一个题:

F.Pulling Their Weight

https://ac.nowcoder.com/acm/contest/12606/F

题意:

输入n个数,分为两组,要求两组数的和相等,给定一个数t,要求t比一组的全部数大,比另一组的全部数小,找出最小的t。

tip:当t和n个数中的数有相同时,如果个数为偶数,就把他们分别分到两组,如果个数为奇数,就剔除一个,变成偶数,按偶数处理。

思路:

先排序,然后用前缀和记录对应区间的和。如果遍历到某个前缀和的2倍正好是所有数的和,那么这个前缀和对应的数+1(最小的t),就是想要的答案,

如果有两个相同元素,那就是这个前缀和对应的a值(因为偶数不会被踢)。还有当某个前缀和*2大于总和,就把这个数作为t。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

int n, a[100010], sum[100010], ans;

int main()
{
    memset(sum, 0, sizeof(sum));
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    sort(a + 1, a + n + 1);

    for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + a[i];

    for (int i = 1; i <= n; i++)
    {
        if (sum[i] * 2 > sum[n])
        {
            ans = a[i];
            break;
        }
        else if (sum[i] * 2 == sum[n])
        {
            if (a[i] == a[i + 1])
            {
                ans = a[i];
                break;
            }
            else
            {
                ans = a[i] + 1;
                break;
            }
        }
    }
    cout << ans << endl;
    return 0;
}

 

"Inference"

思路还挺巧的

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1000010;

typedef long long LL;

LL n;
LL a[N];
LL sum[N];

int main()
{
    cin >> n;
    for(int i = 1 ; i <= n ; i ++ ) cin >> a[i] , sum[i] = sum[i - 1] + a[i];
    
    for(int t = n ; t >= 1 ; t -- )//从大到小枚举所有的t
        for(int i = 0 ; i <= n - t ; i ++ )//枚举所有的连续t个数之和
        {
            if((sum[i + t] - sum[i]) % n == 0)
            {
                cout << t << endl;
                return 0;
            }
        }

    cout << -1 << endl;
    
    return 0;
}

 

posted @ 2021-03-17 10:42  彦辰kkkkk  阅读(242)  评论(0)    收藏  举报