题目描述
题解
一段区间的sigma可以转化为前缀和相减
而如果将前缀和都取模m意义下那么所有的都变成了1..m-1中的一个数
那么如果当前的前缀和为x,如何查询x-?的最大值
如果之前的前缀和有比x大的数y,那么答案一定为(x-y)%m
否则为x%m
x-y<0 -> (x-y)%m=m-(y-x)
y<=m -> m-(y-x)>=x
所以实际上就是查询一下是否有比x大的数
那我们拿treap/splay什么的随便维护一下就行了
当然set随便水
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<set>
using namespace std;
#define LL long long
const LL inf=1000000000000000001LL;
int n;
LL m,x,sum,now,ans;
set <LL> s;
int main()
{
scanf("%d%lld",&n,&m);
ans=0;sum=0;
s.insert(0);s.insert(inf);
for (int i=1;i<=n;++i)
{
scanf("%lld",&x);x=(x%m+m)%m;
sum=((sum+x)%m+m)%m;s.insert(sum);
if (*s.upper_bound(sum)!=inf) now=*s.upper_bound(sum);
else now=*s.begin();
ans=max(ans,((sum-now)%m+m)%m);
}
printf("%lld\n",ans);
}