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;
}