题解 CF950B 【Intercepted Message】
维护两个前缀和+双指针查找即可
这道题我做的时候看的标签居然是贪心。。。也是无语了(希望管理大大改下标$签) 1. 根据题意得,既然想要求最多可以分成几段每一段满足第一个数组的第q段元素之和,第二个数组的第q段元素之和相等。那么首先需要维护一个前缀和来存条件中的q段元素之和。 1. 然后在用四个指针,$l_i$和$i$ :$i$指向第一个数组的从$l_i$开始以$i$结尾的前缀和,$l_j$和$j$同理。 1. 然后$i$和$j$从1开始每次查找,如果第一个数组的$i-l_i$的前缀和$=$第二个数组的$j-lj$的前缀和,就满足了条件,答案$+1$。如果$i-l_i$的前缀和$<j-l_j$的前缀和,那就让$i++$,让$i+1-l_i$的前缀和再与$j-l_j$的前缀和比较,$j-l_j$的前缀和$<i-l_i$的前缀和的情况同理。
大概思路就是这些了,下面给出代码实现方便理解请忽略快读和快输
#include<cstdio>
#include<cctype>
inline int max(int a,int b){
return a>b?a:b;
}
inline int read(int &x){
x=0;char ch=0;int sign=1;
do{ch=getchar();if(ch=='-')sign=-1;}while(!isdigit(ch));
do{x=x*10+ch-48;ch=getchar();}while(isdigit(ch));
x*=sign;
}
inline void out(int x){
if(x<0){
x=-x;
putchar('-');
}
if(x>9){
out(x/10);
}
putchar(x%10+'0');
}
int n,m,a1[1000010],a2[1000010],dp1[1000010],dp2[1000010];
int main(){
read(n);read(m);
for(register int i=1;i<=n;i++){
read(a1[i]);
if(i==1)dp1[1]=a1[1];
else dp1[i]=dp1[i-1]+a1[i];
}
for(register int i=1;i<=m;i++){
read(a2[i]);
if(i==1)dp2[1]=a2[1];
else dp2[i]=dp2[i-1]+a2[i];
}
int i=1,j=1,li=0,lj=0,ans=0;
while(i<=n&&j<=m){
if(i==li)i=li+1;
if(j==lj)j=lj+1;
if(dp1[i]-dp1[li]==dp2[j]-dp2[lj]){
ans++;li=i,lj=j;
}else{
if(dp1[i]-dp1[li]>dp2[j]-dp2[lj]){
j++;
}
if(dp1[i]-dp1[li]<dp2[j]-dp2[lj]){
i++;
}
}
}
out(ans-1);
return 0;
}