开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 11 天,点击查看活动详情
题目:3956. 截断数组
分析
这是一个前缀和的不错的题目,题目要求是要在一个数组内划两条线,这个数组的三部分之和是一样大的,这题首先考虑暴力枚举会发现几乎没办法写,然后我们就想到了前缀和,可以用前缀和将这个数组分成三段s[i],s[j]-s[i],s[n]-s[j],这三段,但是这种想法比较朴素,枚举的复杂度也特别的高,我们可以近一步想首先这个总和s[n]一定要是3的倍数否则一定分不出三个相等组,近一步我们可以考虑枚举s[n]/2和是2s[n]/3这些点的位置,因为无论怎么划分,前i个数一定是s[n]/3,中间一定是2s[n]/3,后面自然就是s[n]了,但是枚举位置时要注意2s[n]/3的点的位置一定要在s[n]/3的点的后面,因此近一步我们可以再考虑一个前缀和s[i]从后往前记录当前位置后面有多少个2s[n]/3的点,然后我们从前往后枚举寻找=s[n]/2的点,加上对应的s[i]就是最后的答案,但是有个地方要注意,第二个前缀和一定要考虑到了如果当前位置是0,那么当前位置不能计入,而且第一个位置和第n个位置也不能计入,因为题目要求非空,这题我wa了很多很多次,wa麻了。 下面是化简之后的代码,最开始AC的那个答辩代码,我就不放出来ex大家了QAQ!
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <map>
#include <set>
#include <iomanip>
#include <cmath>
#include <unordered_map>
#include <stack>
#include <queue>
#define ll long long
#define lowbit(x) x&(-x)
using namespace std;
typedef pair<int,int> PII;
typedef pair<string,int> PSI;
typedef stack<int> stk;
int gcd(int x,int y){
return y?gcd(y,x%y):x;
}
ll qmi(ll x,ll y,int mod){
ll res=1;
while(y){
if(y&1) res=res*x%mod;
y>>=1;
x=x*x%mod;
}
return res;
}
const int N=100010;
ll a[N],n,cnt[N],res=0,s[N],ans=0;;
bool ok[N];
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
a[i]+=a[i-1];
}
if(a[n]%3) cout<<0<<"\n";
else{
for(int i=n-1;i>=2;i--){
if(a[i]==2*a[n]/3) cnt[i]=1;
}
for(int i=n;i>=1;i--){
s[i]=s[i+1]+cnt[i+1];
}
for(int i=1;i<=n;i++){
if(a[i]==a[n]/3) ans+=s[i];
}
cout<<ans<<"\n";
}
return 0;
}
希望对大家有帮助,QAQ!