poj 2566 Bound Found (前缀和,尺取法(two pointer))


Bound Found

Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 2010   Accepted: 659   Special Judge

Description

Signals of most probably extra-terrestrial origin have been received and digitalized by The Aeronautic and Space Administration (that must be going through a defiant phase: "But I want to use feet, not meters!"). Each signal seems to come in two parts: a sequence of n integer values and a non-negative integer t. We‘ll not go into details, but researchers found out that a signal encodes two integer values. These can be found as the lower and upper bound of a subrange of the sequence whose absolute value of its sum is closest to t.

You are given the sequence of n integers and the non-negative target t. You are to find a non-empty range of the sequence (i.e. a continuous subsequence) and output its lower index l and its upper index u. The absolute value of the sum of the values of the sequence from the l-th to the u-th element (inclusive) must be at least as close to t as the absolute value of the sum of any other non-empty range.

Input

The input file contains several test cases. Each test case starts with two numbers n and k. Input is terminated by n=k=0. Otherwise, 1<=n<=100000 and there follow n integers with absolute values <=10000 which constitute the sequence. Then follow k queries for this sequence. Each query is a target t with 0<=t<=1000000000.

Output

For each query output 3 numbers on a line: some closest absolute sum and the lower and upper indices of some range where this absolute sum is achieved. Possible indices start with 1 and go up to n.

Sample Input

5 1
-10 -5 0 5 10
3
10 2
-9 8 -7 6 -5 4 -3 2 -1 0
5 11
15 2
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
15 100
0 0

Sample Output

5 4 4
5 2 8
9 1 1
15 1 15
15 1 15

Source

Ulm Local 2001

题意 :给定一个长度为n的区间.然后给k次询问,每次一个数t,求一个区间[l,r]使得这个区间和的绝对值最接近t

没办法直接尺取.

先预处理出来前缀和

如果要找一对区间的和的绝对值最最近t

等价于找到两个数i和j,使得sum[i]-sum[j]的绝对值最接近t,且i<>j

那么对前缀和排序...然后尺取

因为答案要输出下标

所以之前先存一下下标.

然后对于i,j

所对应的区间为[min(pre[i].id,pre[j].id)+1,max(pre[i],id,pre[j].id)];

  1 /*************************************************************************
  2     > File Name: code/poj/2566.cpp
  3     > Author: 111qqz
  4     > Email: [email protected]
  5     > Created Time: 2015年09月24日 星期四 22时10分08秒
  6  ************************************************************************/
  7
  8 #include<iostream>
  9 #include<iomanip>
 10 #include<cstdio>
 11 #include<algorithm>
 12 #include<cmath>
 13 #include<cstring>
 14 #include<string>
 15 #include<map>
 16 #include<set>
 17 #include<queue>
 18 #include<vector>
 19 #include<stack>
 20 #include<cctype>
 21 #define y1 hust111qqz
 22 #define yn hez111qqz
 23 #define j1 cute111qqz
 24 #define ms(a,x) memset(a,x,sizeof(a))
 25 #define lr dying111qqz
 26 using namespace std;
 27 #define For(i, n) for (int i=0;i<int(n);++i)
 28 typedef long long LL;
 29 typedef double DB;
 30 const int N=1E5+7;
 31 const int inf = 0x3f3f3f3f;
 32 int a[N];
 33 int n ,k;
 34 struct Q
 35 {
 36     int id;
 37     int sum;
 38 }pre[N];
 39
 40 bool cmp(Q a,Q b)
 41 {
 42     if (a.sum<b.sum) return true;
 43     if (a.sum==b.sum&&a.id<b.id) return true;
 44     return false;
 45 }
 46
 47 void solve ( int t)
 48 {
 49     int ansl,ansr,ans;
 50     int l = 0 ;
 51     int r = 1;
 52     int mi = inf;
 53     while ( r<= n )
 54     {
 55     int tmp = pre[r].sum - pre[l].sum;
 56
 57     if (abs(tmp-t)<mi)
 58     {
 59         mi = abs(tmp-t);
 60         ansl = min(pre[l].id,pre[r].id)+1;
 61         ansr = max(pre[l].id,pre[r].id);
 62         ans = tmp;
 63     }
 64     if (tmp<t)
 65     {
 66         r++;
 67     }
 68     else
 69     if (tmp>t)
 70     {
 71         l++;
 72     }
 73     else break;
 74
 75     if (l==r) r++;
 76     }
 77     printf("%d %d %d\n",ans,ansl,ansr);
 78 }
 79
 80 int main()
 81 {
 82   #ifndef  ONLINE_JUDGE
 83    freopen("in.txt","r",stdin);
 84   #endif
 85     while (scanf("%d %d",&n,&k)!=EOF)
 86     {
 87     if (n==0&&k==0) break;
 88     pre[0].id = 0 ;
 89     pre[0].sum = 0 ;
 90     for ( int i = 1 ; i <= n ; i++)
 91     {
 92         scanf("%d",&a[i]);
 93         pre[i].sum = pre[i-1].sum + a[i];
 94         pre[i].id = i ;
 95        // cout<<pre[i].sum<<" ";
 96     }
 97 //    cout<<endl;
 98
 99     sort(pre,pre+n+1,cmp);
100 //    for ( int i = 0 ; i <= n ; i++) cout<<pre[i].sum<<" "; cout<<endl;
101     for ( int i = 1 ; i <= k ; i++)
102     {
103         int x;
104         scanf("%d",&x);
105         solve(x);
106     }
107     }
108
109  #ifndef ONLINE_JUDGE
110   fclose(stdin);
111   #endif
112     return 0;
113 }

时间: 2024-10-13 22:03:52

poj 2566 Bound Found (前缀和,尺取法(two pointer))的相关文章

poj 3320 Jessica&#39;s Reading Problem(尺取法+map/hash)

题目:http://poj.org/problem?id=3320 题意:给定N个元素的数组,找出最短的一段区间使得区间里面的元素种类等于整个数组的元素种类. 分析:暴力枚举区间的起点x,然后找到最小的y,使得区间[x,y]满足条件,x向有移位后变成x',现在的y'肯定不至于在y的左边.存状态的话map和hash都可以. map代码: #include <iostream> #include <set> #include <map> #include <cstdi

poj 3320 Jessica&#39;s Reading Problem (尺取法)

Jessica's Reading Problem Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8787   Accepted: 2824 Description Jessica's a very lovely girl wooed by lots of boys. Recently she has a problem. The final exam is coming, yet she has spent littl

POJ 3320 Jessica&#39;s Reading Problem 尺取法/map

Jessica's Reading Problem Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7467   Accepted: 2369 Description Jessica's a very lovely girl wooed by lots of boys. Recently she has a problem. The final exam is coming, yet she has spent littl

POJ - 2566 Bound Found(尺取法+前缀和)

题目链接:http://poj.org/problem?id=2566 题意:给定一个序列(n个整数)和一个整数k(m个),求出这个序列的一个子串,使之和的绝对值与k的差最小. 尺取法的题目有两个特性: 1. 所求的序列是一个连续的序列,这样才能将序列抽象成一个头和一个尾来描述. 2. 头尾枚举的序列满足某种单调的性质,这样才能进行尺取的操作. 这个序列是一个随意的序列,不可能直接对其进行操作,先要预处理下,进行前缀和操作,把对应的值和标记放在同一个pair. 然后根据前缀和的值进行排序,这样就

poj 2566 Bound Found 尺取法 变形

Bound Found Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 2277   Accepted: 703   Special Judge Description Signals of most probably extra-terrestrial origin have been received and digitalized by The Aeronautic and Space Administration

poj 2566 Bound Found(尺取法 好题)

Description Signals of most probably extra-terrestrial origin have been received and digitalized by The Aeronautic and Space Administration (that must be going through a defiant phase: "But I want to use feet, not meters!"). Each signal seems to

POJ - 2566 Bound Found

题意:询问一个静态序列的连续区间和绝对值最接近t的下标. 分析:由于询问的是绝对值,可以用前缀和相减得到区间和,并且和位置前后没有关系.于是把记录下标信息以后把 前缀和排序枚举大的前缀pj,pj-pi ≍ t,满足条件的:有pj-t的plower_bound以及plower_bound-1. 而pj-t也是单调的,再用一个下标i去维护就好. /********************************************************* * -----------------

poj 2566Bound Found(前缀和,尺取法)

http://poj.org/problem?id=2566: 题意:找连续的串,求和绝对值与所给数字最接近的串. 思路:先求下标为1的到其他下的串的值,也就是前缀和:这样可以在O(1)的时间内求出各个串的和.比如S1(1,1),S3(1,3); 那么S3-S1就是S(2,3): 然后对上面所求的前缀和按从小到大排序.(因为取的是绝对值所以abs(Sn-Sk)==abs(Sk-Sn)); 这样就可以用尺取法去做了.复杂度为O(n); 还可以用二分取找值,复杂度为O(n*log(n)); 1 #i

POJ 2566(尺取法

自己看了半天并没有看出这题怎么用尺取法(虽然一看就觉得肯定是尺取法..),由于是绝对值,那么在计算的时候头和尾的实际位置并不重要,而应用尺取法这个数列肯定得是单调,那么我们把前缀和处理出来排序就可以直接应用尺取法了 #include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<utility> #include<vector> #inc