题解 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;
}
posted @ 2018-11-04 00:37  加固文明幻景  阅读(5)  评论(0编辑  收藏  举报  来源