51nod 1094

来源:互联网 发布:奇葩说肖骁 知乎 编辑:程序博客网 时间:2024/05/17 01:49

这题主要是有负数,如果没有负数的话我觉得到可以用尺取法做一做、

我这题的思路做一个前缀和并记录那个前缀的末位置,排序前缀和,类似暴力枚举的思路 判断sum[i] - sum[j] = k, 枚举每一个前缀分别是sum[i]还是sum[j]讨论 这里用二分找,我们找到数组里面第一个大于等于这个数的位置,然后依次向前推,看是否满足条件,因为满足的位置可能不止一个所以要向前推,注意这里要保证i最小的情况下j最小,这里还有一些要注意的细节,比如一个数的时候,比如就是前缀和的时候、

#include<cmath>#include<cstring>#include<cstdio>#include<algorithm>#include<vector>using namespace std;const int qq = 10010;struct Segment{int id;long long sum;bool operator < (const Segment &a)const{return sum<a.sum;} }seg[qq];long long dp[qq];int find(long long x, long long n){int l=1, r=n;int m;while(l<r){m = (l+r)/2;if(seg[m].sum>=x)r = m;elsel = m+1;}return l;}int main(){long long n,m;scanf("%lld%lld",&n,&m);long long sum = 0;long long x;int ans = 1e9, cns;for(int i=1; i<=n; ++i){scanf("%lld",&x);if(x==m&&ans==1e9)ans=cns=i;sum+=x;seg[i].id = i;seg[i].sum = sum;if(sum==m)ans=1,cns=i;}sort(seg+1, seg+n+1);//for(int i=1; i<=n; ++i)//dp[i] = seg[i].sum;for(int i=1; i<=n; ++i){//printf("%d \n", seg[i].id);int id;//id = lower_bound(dp+1, dp+1+n, seg[i].sum-m)-dp;id = find(seg[i].sum-m, n);if(id!=-1&&seg[i].id>seg[id].id){int c = id;while(seg[c].sum==seg[i].sum-m&&seg[i].id>seg[id].id){if(ans>seg[id].id+1)ans=seg[id].id+1,cns=seg[i].id;else if(ans==seg[id].id+1)cns=min(cns, seg[i].id);c++;}}//id = lower_bound(dp+1, dp+1+n, seg[i].sum+m)-dp;id = find(seg[i].sum-m, n);if(id!=-1&&seg[id].id>seg[i].id){int c = id;while(seg[c].sum==seg[i].sum+m&&seg[id].id>seg[i].id){if(ans>seg[i].id+1)ans=seg[i].id+1,cns=seg[id].id;else if(ans==seg[i].id+1)cns = min(cns, seg[id].id);c++;}}//printf("%d %d\n", ans, cns);}if(ans!=1e9)printf("%d %d\n", ans, cns);elseprintf("No Solution\n");}



0 0
原创粉丝点击