poj2566 尺取法
Posted xiaobuxie
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj2566 尺取法相关的知识,希望对你有一定的参考价值。
传送门:https://vjudge.net/problem/POJ-2566
题意 :给出一个整数列,有正数和负数,求一段子串之和的绝对值最接近所给出的t。并输出该段子序列之和及左右端点。
听了胡老师的建议,最近都是以挑战程序设计竞赛为主线。这题也是从那里过来的。其实尺取法就是双指针,但是要注意单调性,就是扫一遍的事情了。
这题其实也是一道水题,只是最近好像不在状态,WA了几次sb错误。
首先说说思路吧,题目给子串,自然而然想到处理前缀和使得O(1)查询子串和。然后按值从小到大排个序,接下来就转换成在前缀和这个数列里面,找两个端点,使得他们的差最接近t。这样就转换成尺取法的常规做法了。双指针,当差比t小时,++r,反之++l。注意边界。
然后用了个pair来搞id。
犯二的点:把anssum初始化为1e9+100,人家t也可以去到1e9的好吧。。。然后sum【0】初始化在循环外。。。。。然后对sum数组排序没有把sum[0]考虑进来。。。。感觉最近状态真的太差了。。
1 // Cease to struggle and you cease to live 2 #include <iostream> 3 #include <cmath> 4 #include <cstdio> 5 #include <cstring> 6 #include <algorithm> 7 #include <queue> 8 #include <vector> 9 #include <set> 10 #include <map> 11 #include <stack> 12 using namespace std; 13 typedef long long ll; 14 pair<ll,int> sum[100000+8]; 15 ll abss(ll a){return a>=0?a:-a;} 16 int n; 17 ll k; 18 #define L min(sum[ansl].second,sum[ansr].second)+1 19 #define R max(sum[ansl].second,sum[ansr].second) 20 void solve(ll q){ 21 int l=0,r=1,ansl=0,ansr=1; 22 ll anss=abss(sum[r].first-sum[l].first); 23 while(1){ 24 ll d=abss(sum[r].first-sum[l].first); 25 if(abss(d-q)<abss(anss-q)){ 26 anss=d; 27 ansl=l; 28 ansr=r; 29 } 30 if(d==q){ 31 printf("%lld %d %d\n",q,L,R); 32 //cerr<<"a"<<l<<‘ ‘<<r<<endl; 33 return; 34 } 35 if(l==n-1 && r==n) break; 36 if(l==r-1) ++r; 37 else if(d>q || r==n) ++l; 38 else ++r; 39 } 40 printf("%lld %d %d\n",anss,L,R); 41 } 42 int main() { 43 while(~scanf("%d%lld",&n,&k)){ 44 if(n==0 && k==0 ) break; 45 sum[0]=make_pair((ll)0,0); 46 for(int i=1;i<=n;++i){ 47 ll t; 48 scanf("%lld",&t); 49 sum[i]=make_pair(sum[i-1].first+t,i); 50 } 51 sort(sum,sum+1+n); 52 for(int i=1;i<=k;++i){ 53 ll q; 54 scanf("%lld",&q); 55 solve(q); 56 } 57 } 58 return 0; 59 }
以上是关于poj2566 尺取法的主要内容,如果未能解决你的问题,请参考以下文章