相当于分成三段,第一段为第一行走的路线总和,第二段为第二行走的路线总和,第三段为第三行走的路线总和。可以枚举第一个分割点,二分查找第二个分割点。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=100100;
long long mz[5][MAXN],pre[5][MAXN];
set<long long> st;
set<long long> ::iterator it;
int main()
{
long long n,mod,i,j,ans,x1,x2;
while(~scanf("%lld%lld",&n,&mod))
{
for(i=1;i<=3;i++)
for(j=1;j<=n;j++)
scanf("%lld",&mz[i][j]);
pre[1][0]=pre[2][0]=pre[3][0]=0;
for(i=1;i<=3;i++)
for(j=1;j<=n;j++)
pre[i][j]=(mz[i][j]+pre[i][j-1])%mod;
st.clear();
ans=0;
for(i=1;i<=n;i++)
{
x1=(pre[1][i]-pre[2][i-1]+mod)%mod;
st.insert(x1);
x2=(pre[3][n]-pre[3][i-1]+pre[2][i]+mod)%mod;
it=st.lower_bound(mod-x2);
ans=max(ans,(x2+*(--it))%mod);
}
printf("%lld\n",ans);
}
}