0
点赞
收藏
分享

微信扫一扫

取余最长路 51Nod - 1624

​​https://www.51nod.com/Challenge/Problem.html#!#problemId=1624​​

一开始考虑枚举第一行 剩下的两行用set维护 但是在枚举过程中 低两行中的数又需要更新 然后陷入僵局

其实把要求的答案列出式子 就是要找一对(i,j)满足i<=j 使得(sum[1][i]+sum[2][j]-sum[2][i-1]+sum[3][n]-sum[3]j-1])%mod值最大

一开始的想法就是拆为sum[1][i]与sum[2][j]-sum[2][i-1]+sum[3][n]-sum[3]j-1]两部分或者类似的 来分别维护 显然不行

那就把式子转换一下 拆为sum[1][i]-sum[2][i-1]与sum[2][j]+sum[3][n]-sum[3]j-1]两部分 即与i相关的放在一起 与j相关的放在一起 这样不管是遍历i或j哪一部分 另外一部分都不用随之发生变化

 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;

ll sum[4][maxn];
ll mod;
int n;

int main()
{
set <ll> st;
set <ll> ::iterator it;
ll val,ans;
int i,j;
scanf("%d%lld",&n,&mod);
for(i=1;i<=3;i++){
for(j=1;j<=n;j++){
scanf("%lld",&val);
val%=mod;
sum[i][j]=(sum[i][j-1]+val)%mod;
}
}
ans=0;
for(i=1;i<=n;i++){
st.insert((sum[1][i]-sum[2][i-1]+mod)%mod);
val=(sum[2][i]+sum[3][n]-sum[3][i-1]+2ll*mod)%mod;
it=st.lower_bound(mod-val);
if(it!=st.begin()){
it--;
ans=max(ans,val+*it);
}

}
printf("%lld\n",ans);
return 0;
}

 


举报

相关推荐

0 条评论