Bound Found [POJ2566] [尺取法]

题意

给出一个整数列,求一段子序列之和最接近所给出的t。输出该段子序列之和及左右端点。

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

分析

这道题可以看得出来是要用尺取法,尺取法的关键是要找到单调性。而序列时正时负,显然是不满足单调性的。

如果记录下前缀和,并排好序,这样就满足单调性了,就可以使用前缀和了

代码

 1 #include<set>
 2 #include<map>
 3 #include<queue>
 4 #include<stack>
 5 #include<cmath>
 6 #include<cstdio>
 7 #include<cstring>
 8 #include<iostream>
 9 #include<algorithm>
10 #define RG register int
11 #define rep(i,a,b)    for(RG i=a;i<=b;++i)
12 #define per(i,a,b)    for(RG i=a;i>=b;--i)
13 #define ll long long
14 #define inf (1<<30)
15 #define maxn 100005
16 using namespace std;
17 int n,k;
18 int num[maxn];
19 struct P{
20     int id,s;
21     inline int operator < (const P &a)const{
22         return s==a.s?id<a.id:s<a.s;
23     }
24 }p[maxn];
25 inline int read()
26 {
27     int x=0,f=1;char c=getchar();
28     while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
29     while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
30     return x*f;
31 }
32
33 void solve()
34 {
35     int aim=read();
36     int l=0,r=1,mn=inf,al,ar,ans;
37     while(l<=n&&r<=n&&mn)
38     {
39         int cal=p[r].s-p[l].s;
40         if(abs(cal-aim)<mn)
41         {
42             mn=abs(cal-aim);
43             al=p[r].id,ar=p[l].id,ans=cal;
44         }
45         if(cal>aim)            ++l;
46         else if(cal<aim)    ++r;
47         else    break;
48         if(l==r)    ++r;
49     }
50     if(al>ar)    swap(al,ar);
51     printf("%d %d %d\n",ans,al+1,ar);
52 }
53
54 int main()
55 {
56     while(1)
57     {
58         n=read(),k=read();
59         if(!n&&!k)    return 0;
60         rep(i,1,n)    num[i]=read();
61         p[0]=(P){0,0};
62         rep(i,1,n)    p[i].s=p[i-1].s+num[i],p[i].id=i;
63         sort(p,p+1+n);
64         rep(i,1,k)    solve();
65     }
66     return 0;
67 }

原文地址:https://www.cnblogs.com/ibilllee/p/9300321.html

时间: 2024-11-09 02:11:37

Bound Found [POJ2566] [尺取法]的相关文章

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(尺取法+前缀和)

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

poj2566 尺取法

题意: 输入 n m  之后输入n个数 之后m个询问  对于每个询问 输入一个t    输出  三个数 ans l r  表示从l 到 r的所有数的和的绝对值最接近t 且输出这个和ans 思路:就是指针的移动. AC代码: #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<limits.h>

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

poj2566尺取变形

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

luogu 1712 区间(线段树+尺取法)

题意:给出n个区间,求选择一些区间,使得一个点被覆盖的次数超过m次,最小的花费.花费指的是选择的区间中最大长度减去最小长度. 坐标值这么大,n比较小,显然需要离散化,需要一个技巧,把区间转化为半开半闭区间,然后线段树的每一个节点表示一个半开半闭区间. 接着我们注意到需要求最小的花费,且这个花费只与选择的区间集合中的最大长度和最小长度有关. 这意味着如果最大长度和最小长度一定,我们显然是需要把中间长度的区间尽量的选择进去使答案不会变的更劣. 不妨把区间按长度排序,枚举每个最小长度区间,然后最大区间

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

hihocoder-1483区间价值 (二分+尺取法)

题目链接: 区间价值 给定n个数A1...An,小Ho想了解AL..AR中有多少对元素值相同.小Ho把这个数目定义为区间[L,R]的价值,用v[L,R]表示. 例如1 1 1 2 2这五个数所组成的区间的价值为4. 现在小Ho想知道在所有的的v[L,R](1 <= L <= R <= n)中,第k小的值是多少. Input 第一行一个数T(T<=10),表示数据组数. 对于每一组数据: 第一行两个数n,k(1<=n<=200,000,1<=k<=n*(n+1

【转】毛虫算法&mdash;&mdash;尺取法

转自http://www.myexception.cn/program/1839999.html 妹子满分~~~~ 毛毛虫算法--尺取法 有这么一类问题,需要在给的一组数据中找到不大于某一个上限的"最优连续子序列" 于是就有了这样一种方法,找这个子序列的过程很像毛毛虫爬行方式,我管它叫毛毛虫算法,比较流行的叫法是"尺取法". 喏,就像图里的妹纸一样~ 还是举个栗子: Poj3061 给长度为n的数组和一个整数m,求总和不小于m的连续子序列的最小长度 输入 n = 1