ACGO挑战赛6 C题数字序列的钥匙 题型:思维 难度:中

67 阅读1分钟

www.acgo.cn/exam/41252?… image.png

思想

我刚开始是这样想的,通过两层循环i,j控制终点位置,对[l,r]区间进行求和,同时再通过一层循环k枚举[l,r]区间每个数,我们控制某个数a[k]不被累加到SUM里.最后我们看一下SUM和这个没被加入到SUM里的a[k]是否相等,如果相等,那么cnt++.

这个算法是暴力做法,时间复杂度1e9,超时

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e3 + 10;
int a[N];
//unordered_set<int>haxi;
map<int, int>haxi;
int cnt, sum, n;
signed main()
{
	cin.tie(nullptr)->sync_with_stdio(false);
	cin >> n;
	for (int i = 1; i <= n; i++)cin >> a[i];

	for (int i = 1; i <= n; i++) //终点
	{
		sum = 0;
		for (int j = 1; j <= i; j++)  //标记哪个不加 
		{
			for (int k = 1; k <= i; k++) //累加区间和 
			{
				if (k != j)
				{
					sum += a[k];
				}haxi[a[k]]++;
			}
			if (haxi.count(sum))
			{
				cnt++;
			}
		}
	}
	cout << cnt << endl;
	return 0;
}

image.png

优解

像这种题暴力做不了的就要先去观察,找规律.

通过观察我们发现,当满足题目要求时,序列中一定有 最大值=sum/2这个条件成立. image.png

image.png

#include<bits/stdc++.h>

#define int long long
using namespace std;
int n;
const int N=2e5+10;
int a[N],sum,cnt,ans=-0x3f3f3f3f;
signed main()
{
	cin.tie(nullptr)->sync_with_stdio(false);
	cin>>n;
	for(int i=0;i<n;i++)cin>>a[i];
	for(int i=0;i<n;i++)
	{
		sum+=a[i];
	    ans=max(a[i],ans);
	    if(ans*2==sum)cnt++;
	} 
	
	cout<<cnt<<endl;
	return 0;
}

image.png