一维前缀和
大部分的题其实都是一维前缀和
我们先来看一下一维前缀和的公式:sum[i] = sum[i - 1] + a[i]
记住这个就够够的了。
前缀和的主要用途就是降低时间复杂度,比如一道题中数据范围n是十的五次方,那么遍历两层循环必然会超时,此时前缀和就是一种做法。
我们来看这一个题:
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; }
思路还挺巧的
#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; }

浙公网安备 33010602011771号