BZOJ 3544 [ONTAK2010]Creative Accounting(set)

 

【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=3544

 

【题目大意】

  找一段区间使得Σai mod m的值最大。

 

【题解】

  首先计算前缀和顺序插入set,对于一个位置为右端点的数来说,
  如果前缀的前缀和中有比其大的数,选择比其大的最小的那个计算用来更新答案一定最优
  如果不存在,则选择set中最小的来计算更新答案。

 

【代码】

#include <cstdio>
#include <algorithm>
#include <set>
using namespace std;
const int N=200010;
typedef long long LL;
const LL INF=0x3f3f3f3f3f3f3f3f;
int n;
LL m,a[N],s[N];
int main(){
    while(~scanf("%d%lld",&n,&m)){
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            a[i]=(a[i]%m+m)%m;
            s[i]=(s[i-1]+a[i])%m;
        }LL t=0;
        LL ans=-INF; set<LL> st;
        st.insert(0);
        for(int i=1;i<=n;i++){
            if(st.upper_bound(s[i])!=st.end())t=*st.upper_bound(s[i]);
            else t=*st.begin();
            ans=max((s[i]-t+m)%m,ans);
            st.insert(s[i]);
        }printf("%lld\n",ans);
    }return 0;
}
posted @ 2017-05-19 01:06  forever97  阅读(207)  评论(0编辑  收藏  举报