题意:3*n(n<1e5)的方格,每个方格内有一个数字,从(1,1)走到(3,n)(只能向下或向右),走过格子的和,膜p后的最大值是多少
题解:如果是普通的不需要膜的话,就是普通的dp,但是有膜以后,会产生后效性,因此,就不会dp了
如果暴力的话,复杂度n^2
换个角度,也就是找两个拐点,使得sum[1][x]+sum[2][y]-sum[2][x-1]+sum[3][n]-sum[3][y-1]最大就可以
考虑优化,对于sum[2][y]-sum[3][y-1]+sum[3][n],只要找到前面的“最大”的sum[1][x]-sum[2][x-1]就可以
可以把前面所有的sum[1][i]-sum[2][i-1]保存起来,然后二分找就可以
int a[10][100010];
LL sum[10][100010];
int main(){
mem(a,0);
mem(sum,0);
int n;
LL p;
cin>>n>>p;
for(int i=1;i<=3;i++){
for(int j=1;j<=n;j++){
scanf("%d",&a[i][j]);
sum[i][j]=(sum[i][j-1]+a[i][j])%p;
}
}
set <int> s;
s.clear();
LL ans=(sum[1][n]+a[2][n]+a[3][n])%p;
for(int i=1;i<=n;i++){
LL temp=(sum[1][i]-sum[2][i-1]+p)%p;
s.insert(temp);
temp=(sum[2][i]-sum[3][i-1]+sum[3][n]+p)%p;
///不超过p,且能达到的最大值
set <int>::iterator it = s.lower_bound(p-temp);
if(it!=s.begin())
ans=max(ans,(temp+*(--it))%p);
}
cout<<ans<<endl;
return 0;
}