ACwing 第16场周赛

B题题目大意:

给定一个长度为 nn 的数组 a1,a2,…,ana1,a2,…,an。

现在,要将该数组从中间截断,得到三个非空子数组。

要求,三个子数组内各元素之和都相等。

请问,共有多少种不同的截断方法?

解题思路:

  这道题目很容易先想到一种情况,也就是说n的个数不超过3或者sum[n]不是3的倍数的时候那么是会直接输出no的

  但是对于这道题目其实如果用暴力的方法去做是o(n^2),时间肯定是行不通的

  那么我们如何才能枚举出来呢?

  首先通过对题目的分析,每一块的数值其实是已经确定了的,每一块的数值都是sum[n] / 3,那么我们需要去找有多少个sum[n]/3,并且累加(因为这些sum[n] / 3都是有效分块),在这之后我们再寻找sum[n] * 2 / 3加上之前的累加个数即可

#include <bits/stdc++.h>
#include <map>
#include <vector>
#define FAST std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
int T;
int n;
ll a[maxn];
ll sum[maxn];
map<ll,ll> mp;
vector<ll> v;
int main()
{
	cin >> n;
	for(int i = 1;i <= n;i++)
	{
		cin >> a[i];
		sum[i] = sum[i - 1] + a[i];
	}
	if(n < 3 || sum[n] % 3 != 0)
	{
	//	cout <<"????"<<endl;
		cout <<"0"<<endl;
	}
	else
	{
		ll ans = 0;
		ll k = sum[n] / 3;
		ll res = 0;
		for(int i = 1;i <= n ;i++)
		{
			if(sum[i] == 2 * k && i < n) ans += res;
			if(sum[i] == k)
			{
			//	cout <<"!!!!"<<endl;
				res++;
			}
		}
		cout<<ans<<"\n";
	}
	return 0;
}

C题:ACwing 3957 子序列

题目描述:

我们称一个序列是有序的,如果该序列是非严格单调递增序列或非严格单调递减序列。

现在,给定一个 nn 个整数的序列 a1,a2,…,ana1,a2,…,an。

请你找到该序列的最短非有序子序列。

注意,子序列不一定连续。

输入格式

第一行包含整数 nn。

第二行包含 nn 个整数 a1,a2,…,ana1,a2,…,an。

输出格式

如果不存在非有序子序列,则输出一行 00。

否则,首先在第一行输出一个整数,表示最短非有序子序列的长度,随后在第二行按顺序输出该子序列的各元素下标。

如果方案不唯一,输出任意合理方案均可。

题目分析:

分析这道题目可以发现这就是一道简单的思维题,只需要找到2个数就能满足条件

如果我们能找到两个不相同并且相邻的数字,对于数字a[i],如果a[i] > a[1]那么a[i + 1]就要小于a[i];

相反若a[i] < a[1]那么a[i + 1] > a[i]

贴一下很简单的代码

#include <bits/stdc++.h>
#define FAST std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
int n;
const int maxn = 1e5 + 10;
int a[maxn];
int main()
{
	FAST
	cin >> n;
	for(int i = 1; i <= n;i++) cin >> a[i];
	int flag = 0;
	int L,R;
	for(int i = 2; i <= n - 1;i++)
	{
		if(a[i] > a[1] && a[i + 1] < a[i])
		{
			flag = 1;
			L = i;
			R = i + 1;
		}
		if(a[i] < a[1] && a[i + 1] > a[i])
		{
			flag = 1;
			L = i;
			R = i + 1;
		}
		if(flag) break;
	}
	if(!flag) cout << "0" << "\n";
	else
	{
		cout<<"3"<<"\n";
		cout <<"1 "<<L<<" "<<R<<"\n"; 
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值