zoukankan      html  css  js  c++  java
  • DLUTOJ 1331 Maximum Sum

    传送门

    Time Limit: 1 Sec  Memory Limit: 128 MB 


     

    Description

    You are given an array of size N and another integer M.Your target is to find the maximum value of sum of subarray modulo M.
    Subarray is a continous subset of array elements.
    Note that we need to find the maximum value of (Sum of Subarray)%M , where there are N*(N+1)/2 possible subarrays.

    Input

    First line contains T , number of test cases to follow. Each test case consits of exactly 2 lines. First line of each test case contain 2 space separated integers N and M, size of the array and modulo value M. 
    Second line contains N space separated integers representing the elements of the array.
    2 ≤ N ≤ 10^5 
    1 ≤ M ≤ 10^14 
    1 ≤ elements of the array ≤ 10^18 
    2 ≤ Sum of N over all test cases ≤ 500000

    Output

    For every test case output the maximum value asked above in a newline.

    Sample Input

    1 5 7 3 3 9 9 5

    Sample Output

    6

    HINT

    Max Possible Sum taking Modulo 7 is 6 , and we can get 6 by adding first and second element of the array


    Source


    Solution:

    $先预处理出数组在模M下的前缀和sum[ ].$

    $枚举区间起点L,然后在sum[L+1, ..., n]上查找两个值:$

    [v_1=max{sum[i]: sum[i] < sum[L]}]

    [v_2=max{sum[i]: sum[i] ge sum[L]}]

    然后用

    [max(v_{1}-a[L]+M, v_{2}-a[L])]

    更新答案


     Implementation:可以用map,也可以用multiset.

    map版

    忘了map自带lower_bound函数,而且只能用这个lower_bound,不能写成lower_bound(b, e, k)

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    const int N(1e5+5);
    map<LL,int> mp;
    int n;
    LL m, a[N];
    
    
    map<LL,int>::iterator it;
    int main(){
        int T;
        for(scanf("%d", &T); T--; ){
            scanf("%d%lld", &n, &m);
            mp.clear();
            for(int i=1; i<=n; i++) scanf("%lld", a+i), a[i]+=a[i-1], a[i]%=m, mp[a[i]]++;
            mp[0]++;
            LL  ans=0;
            for(int i=0; i<n; i++){
                mp[a[i]]--;
                if(!mp[a[i]]) mp.erase(a[i]);
                ans=max(ans, ((--mp.end())->first-a[i]+m)%m);
                it=mp.lower_bound(a[i]);
                if(it!=mp.begin())
                    ans=max(ans, (--it)->first-a[i]+m);
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }

    multiset 版

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    const int N(1e5+5);
    multiset<LL> ms;
    int n;
    LL m, a[N];
    
    multiset<LL>::iterator it;
    
    int main(){
        int T;
        for(scanf("%d", &T); T--; ){
            scanf("%d%lld", &n, &m);
            ms.clear();
            for(int i=1; i<=n; i++) scanf("%lld", a+i), a[i]+=a[i-1], a[i]%=m, ms.insert(a[i]);
            ms.insert(0);
            LL  ans=0;
            for(int i=0; i<n; i++){
                it=ms.find(a[i]);
                ms.erase(it);
                ans=max(ans, (*--ms.end()-a[i]+m)%m);
                it=ms.lower_bound(a[i]);
                if(it!=ms.begin())
                    ans=max(ans, *--it-a[i]+m);
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }

    写这道题主要是复习C++ STL。上面提到的查询也可以用划分树来写,不过麻烦了许多。BST又不会敲,sigh。。。。。

  • 相关阅读:
    [题解] [JSOI2015] 圈地
    [题解] [JSOI2015] 最小表示
    [题解] [JSOI2015] 套娃
    [题解] [JSOI2015] 非诚勿扰
    [题解] [JSOI2015] 送礼物
    [题解] [JSOI2015] 送礼物
    [题解] [JSOI2015] 子集选取
    [题解] [JSOI2015] salesman
    AC自动机学习笔记
    [题解] [JSOI2014] 矩形并
  • 原文地址:https://www.cnblogs.com/Patt/p/5392308.html
Copyright © 2011-2022 走看看