DLUTOJ 1331 Maximum Sum
Time Limit: 1 Sec Memory Limit: 128 MB
Description
Input
Output
For every test case output the maximum value asked above in a newline.
Sample Input
Sample Output
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\n", 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\n", ans); } return 0; }
写这道题主要是复习C++ STL。上面提到的查询也可以用划分树来写,不过麻烦了许多。BST又不会敲,sigh。。。。。