一、首先介绍一下什么叫尺取
过程大致分为四步:
1.初始化左右端点,即先找到一个满足条件的序列。
2.在满足条件的基础上不断扩大右端点。
3.如果第二步无法满足条件则到第四步,否则更新结果。
4.扩大左端点,并且回到第二步。
很明显如果要这样做,那么这个序列要是一个有顺序的序列,因为这样的话保证左端点不变,右端点一直向右延伸一定会使答案靠近结果。(可以看一道题理解一下)
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.
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
题意:
这道题是让找一段连续序列,保证找到的这一段序列的(所有数和的绝对值)很靠近那个输入。如果找出来的答案有多个,输出任意一个
题解:
因为这一个输入的n个数的序列不是有序的,是没有办法尺取的(可以想想为什么)
因为我们要找出来一段连续的序列,那么就可以利用前缀和。计算出前缀和之后,对他们排序就可以得到一个有序的序列
这样的话我们保证左端点不变的前提下,右端点向右扩展的话会导致这中间的差值就会越来越大,我们只需要找出来能使右端点减去左端点的值更接近答案的区间就可以(右端点减去左端点的值的几何意义就是左端点在原序列中序号和右端点在原序列中序号之间的和)
代码:
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 #include<stdlib.h> 5 #include<algorithm> 6 using namespace std; 7 const int maxn=100005; 8 const int INF=0x3f3f3f3f; 9 struct shudui 10 { 11 int first,second; 12 } p[maxn]; 13 bool cmp(shudui x,shudui y) 14 { 15 return x.first<y.first; 16 } 17 int n,m; 18 void solve(int k) 19 { 20 int l = 0, r = 1, al, ar, av, minn =INF; 21 while (l<=n&&r<=n&&minn!=0) 22 { 23 int temp=p[r].first - p[l].first; 24 if (abs(temp - k) < minn) 25 { 26 minn = abs(temp - k); 27 ar = p[r].second; 28 al = p[l].second; 29 av = temp; 30 } 31 if (temp> k) //当temp>k之后就不用l++,因为之后的答案肯定不如之前的答案更优 32 l++; 33 else if (temp < k) 34 r++; 35 else 36 break; 37 if (r == l) 38 r++; 39 } 40 if(al>ar) 41 swap(al,ar);//因为al和ar大小没有必然关系()取绝对值,所以要交换 42 printf("%d %d %d ", av, al+1, ar); 43 } 44 int main() 45 { 46 int k; 47 48 while(~scanf("%d%d",&n,&m)) 49 { 50 if (!n&&!m) return 0; 51 p[0].second=p[0].first=0; //这一个初始化要放在里面 52 for (int i = 1; i <= n; i++) 53 { 54 scanf("%d", &p[i].first); 55 p[i].first += p[i - 1].first; 56 p[i].second = i; 57 } 58 sort(p, p + n + 1,cmp); 59 while (m--) 60 { 61 scanf("%d", &k); 62 solve(k); 63 } 64 } 65 return 0; 66 }