PAT (Advanced Level) Practice 1044 Shopping in Mars (前缀和 二分)
作者:互联网
题意:
给出
n
n
n个数和
m
m
m,问是否能选择一段连续区间使得和为
m
m
m
如果不能的话,选择和大于
m
m
m并且和
m
m
m的差值最小的区间们。
思路:
求出前缀和后,数组一定是单调的,可以枚举区间的右端点,二分找区间的左端点。
代码:
23分
#include<bits/stdc++.h>
#include<bitset>
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
const int maxn=1e6+7;
ll n,m,a[maxn],sum[maxn];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i],sum[i]=sum[i-1]+a[i];
vector<PII>ans;
ll minn=1e9;
for(int i=1;i<=n;i++){
ll now=sum[i]-m;
int pos=upper_bound(sum+1,sum+1+n,now)-(sum+1);
if(sum[pos]==now) ans.push_back({pos+1,i});
if(sum[i]-sum[pos]-m>0)
minn=min(minn,(sum[i]-sum[pos]-m));
// cout<<i<<" "<<pos<<endl;
}
if(ans.size()==0){
for(int i=1;i<=n;i++){
ll now=sum[i]-m;
int pos=upper_bound(sum+1,sum+1+n,now)-(sum+1);
ll tmp=abs(sum[i]-sum[pos]-m);
if(tmp==minn) ans.push_back({pos+1,i});
}
}
for(int i=0;i<ans.size();i++)
cout<<ans[i].first<<"-"<<ans[i].second<<"\n";
return 0;
}
wa在测试点3
4 10
8 1 12 11
ans:4-4
满分代码
#include<bits/stdc++.h>
#include<bitset>
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
const int maxn=1e6+7;
ll n,m,a[maxn],sum[maxn];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i],sum[i]=sum[i-1]+a[i];
vector<PII>ans;
ll minn=1e9;
for(int i=1;i<=n;i++){
ll now=sum[i]-m;
int pos=lower_bound(sum,sum+1+n,now)-(sum);
if(sum[pos]==now) ans.push_back({pos+1,i});
else pos--;
if(sum[i]-sum[pos]-m>0)
minn=min(minn,(sum[i]-sum[pos]-m));
//cout<<i<<" "<<pos<<endl;
}
//cout<<minn<<endl;
if(ans.size()==0){
for(int i=1;i<=n;i++){
ll now=sum[i]-m;
int pos=lower_bound(sum,sum+1+n,now)-(sum)-1;
if(pos==-1) continue;
ll tmp=abs(sum[i]-sum[pos]-m);
if(tmp==minn) ans.push_back({pos+1,i});
}
}
for(int i=0;i<ans.size();i++)
cout<<ans[i].first<<"-"<<ans[i].second<<"\n";
return 0;
}
标签:Shopping,minn,1044,int,sum,Practice,pos,now,ll 来源: https://blog.csdn.net/weixin_45675097/article/details/120640106