思路一:枚举区间头尾i,j,然后对i和j里面所有数字累加起来求和,再判断是否在不大于M的情况下最大。
#include<iostream>
using namespace std;
int a[8000005];
int main() {int n, M, ansm = 0, ai, aj;cin >> n >> M;for (int i = 1; i <= n; i++) {cin >> a[i];}for (int i = 1; i <= n; i++) {for (int j = i; j <= n; j++) {int sum = 0;for (int k = i; k <= j; k++) {sum += a[k];}if (sum <= M && sum > ansm) {ansm = sum;ai = i;aj = j;}}}cout << ai << " " << aj << " " << ansm;return 0;
}
结果只有惨不忍睹的10分。
思路二:使用前缀和快速求出区间和。
#include<iostream>
using namespace std;
int a[8000005], s[8000005];
int main() {int n, M;int ansm = 0, ai, aj;cin >> n >> M;s[0] = 0;for (int i = 1; i <= n; i++) {cin >> a[i];s[i] = s[i - 1] + a[i];}for (int i = 1; i <= n; i++) {for (int j = i; j <= n; j++) {int sum = s[j] - s[i - 1];if (sum <= M && sum > ansm) {ansm = sum;ai = i;aj = j;}}}cout << ai << " " << aj << " " << ansm;return 0;
}
挽救了20分,变成30分。
思路三:还要快(比赛的时候能骗到这些分就够了)该怎么办呢?尝试用二分。
#include<iostream>
using namespace std;
int a[8000005];
long long n,M,s[8000005];
int find(long long x){int l=1,r=n+1;while(l<r){int mid=(l+(r-1))/2;if(s[mid]>=x){r=mid;}else{l=mid+1;}}if(s[l]==x){return l;}else{return l-1;}
}
int main(){long long ansm=0;int ai,aj;cin>>n>>M;s[0]=0;for(int i=1;i<=n;i++){cin>>a[i];s[i]=s[i-1]+a[i];}for(int i=1;i<=n;i++){long long x=s[i-1]+M;int j=find(x);long long sum=s[j]-s[i-1];if(sum<=M&&sum>ansm){ansm=sum;ai=i;aj=j;}}cout<<ai<<" "<<aj<<" "<<ansm;return 0;
}
终于AC啦。