首页 > 代码库 > 【尺取法好题】POJ2566-Bound Found
【尺取法好题】POJ2566-Bound Found
【题目大意】
给出一个整数列,求一段子序列之和最接近所给出的t。输出该段子序列之和及左右端点。
【思路】
……前缀和比较神奇的想法。一般来说,我们必须要保证数列单调性,才能使用尺取法。
预处理出前i个数的前缀和,和编号i一起放入pair中,然而根据前缀和大小进行排序。由于abs(sum[i]-sum[j])=abs(sum[j]-sum[i]),可以忽视数列前缀和的前后关系。此时,sum[r]-sum[l]有单调性。
因此我们可以先比较当前sum[r]-sum[l]与t的差,并更新答案。
如果当前sum[r]-sum[l]<t,说明和还可以更大,r++。
同理,如果sum[r]-sum[l]>t,说明和还可以更小,l++。
如果sum[r]-sum[l]=t,必定是最小答案。
【注意点】
由于序列不能为空,即l<>r,如果l=r则r++。
我们更新答案的时候左右区间端点为乱序,输出的时候调整一下。
就OK了!
*本来想要尺取弄一个合集,然而这道题做的时候想了半天。还是单独拿出来吧orz
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 const int MAXN=1e5+5; 8 const int INF=2147483640; 9 pair<int,int> sum[MAXN];10 int n,k,t;11 12 void init()13 {14 sum[0]=make_pair(0,0);15 int tmp=0;16 for (int i=1;i<=n;i++) 17 {18 int x;19 scanf("%d",&x);20 tmp+=x;21 sum[i]=make_pair(tmp,i);22 }23 sort(sum,sum+n+1); 24 }25 26 void solve()27 {28 scanf("%d",&t);29 int l=0,r=1,minans=INF,ans,ansl,ansr;30 while (r<=n && minans)//这里一开始写成了ans,以后变量名不要取那么相像orz 31 {32 int delta=sum[r].first-sum[l].first;33 if (abs(delta-t)<=minans)34 {35 minans=abs(delta-t);36 ans=delta;37 ansl=sum[l].second;38 ansr=sum[r].second;39 }40 if (delta<t) r++; 41 if (delta>t) l++;42 if (l==r) r++;//☆注意序列不能为空!43 }44 if (ansl>ansr) swap(ansl,ansr);//注意排序后是无序的,左右区间要调整回有序 45 printf("%d %d %d\n",ans,ansl+1,ansr); 46 }47 48 int main()49 {50 while (scanf("%d%d",&n,&k)!=EOF) 51 {52 init();53 for (int i=1;i<=k;i++) solve();54 }55 return 0;56 }
【尺取法好题】POJ2566-Bound Found
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。