挑战程序设计竞赛3.2习题:Bound Found POJ - 2566

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这道题,ennn卡了我好久,一直不知道怎么去尺取。。。。。。其实,对于每一段(a, b](特别注意是前开后闭区间),我们都可以把这一段的和看成从第一个加到第b个减去从第一个加到第a个的差,这样我们就能计算了。自于尺取的话,我们应当在判断每种情况下区间与t的差值,如果差值小,我们就更新,首先我们对所有的和进行排序。至于怎么取,我们可以分以下几种情况:1.从一开始判断,一开始就取第一个,左边界是0(因为前开后闭),右边界是1,如果第一个的值小于t,我们也可以取第二个(即右边界++),一直这样。2.当进行情况1时出现取的区间和大于t时(假设此时区间为(0,a]),继续增大和将使得与t的差值肯定大于此时的差值(我们都知道,如果和是单调递增的,那么区间的值会先向t逼近,然后又远离t,因为t大于等于0,而和又一直上涨,所以与t的差值是先减小,后增大),所以出现了右边界减去左边界大于t时,之后右边界++后的和与t的差值肯定大于当前,所以没有必要继续下去。接下来怎么办,我们考虑移动左边界,那右边界要不要发生变化呢?如果从第二个开始(即从(1,2]开始),又依次循环到比t大的,时间复杂度很高,尺取的优势就在这里了:在右边界小于a(我们假设右边界为b(b < a)),左边界大于0的情况下都是在(0,b]包含内的,而b < a,则(0, b]因为b < a而(0, a]才是第一次大于t,所以(0,b]<t,故有(1,b] < (0, b] < t,所以(0, b]与t的差值小于(1,b]与t的差值,所以当左边界向右移动的时候,右边界如果小于a都不可能出现差值比之前小的值,我们也就不用去搜索,但是(1,a]我们并不知道是否大于t,所以我们还是得判断,同样如果小于t,还是按照情况1的方法。3.特别情况,因为是前开后闭区间,所以左边界不能等于右边界,这样的值是不存在的,当t==0时,如果放任这种情况就会更新最小的差值就会出错,我们应当把它转变成下一种情况,也就是右边界++。4.对于当最小差值为0时,没有必要继续判定了,直接break;至于排序,我们直接按照从第一个加到第n个的和的顺序进行排序,这样可以使得每次右边界++时和都会大于先前的,才能使得序列具有单调性,而单调性不能少,如果少了就不能正确得出答案。特别的不要忘记排序的时候前0个也要带上,因为真正的左区间可能取第0个也就是从1开始算起,至于排序可能造成的左区间大于右区间的情况,我们结果只要对调一下就好了,值还是不变的,详见代码。归纳一下:1.如果区间和小于t,则右边界++;2.如果区间和大于t,则左边界++;3.如果区间和等于t,直接break;4.如果左右边界相同,右边界++;AC代码:
#include <stdio.h>
#include <algorithm>
using namespace std;
long long abst(long long a)//abs好像不支持long long,不过好像说这道题int也能过
{
    return a >= 0? a:-a;
}
typedef long long ll;
const ll INF = 0x3fffffffffffffff;
ll a[100005];//记录原始序列,但是好像没有必要,直接一个变量就好了
struct Node {
    ll sum;//1到i的和
    ll i;
}sum[100005];
ll q;//询问的值
ll min_s, min_e;//最小的起始末尾
bool cmp(Node x, Node y)
{
    if(x.sum == y.sum)
        return x.i < y.i;
    return x.sum < y.sum;
}

int main(void)
{
    ll n, k;
    while(scanf("%lld %lld",&n, &k) && n + k)
    {
    	sum[0].sum = sum[0].i = 0;//一定要注意每次排完序sum第一个值不一定都是0
        for(ll i = 1; i <= n; i++)
        {
            scanf("%lld", &a[i]);
            sum[i].sum = sum[i - 1].sum + a[i];
            sum[i].i = i;
        }
        sort(sum , sum + n + 1, cmp);//记得排序带上sum【0】,代表着从第0个作为开区间也就是从第一个算起,因为是前开区间,所以left的范围是【0,n - 1】,right的范围是【1,n】
        for(ll i = 0; i < k; i++)
        {
            scanf("%lld", &q);
            ll min_cut = INF;//与t最小差值
            ll value;//区间值
            ll left = 0, right = 1;//左右边界,前开后闭
            while(right <= n)
            {
                if(abst(abst(sum[right].sum - sum[left].sum) - q) <= min_cut)
                {
                    min_cut = abst(abst(sum[right].sum - sum[left].sum) - q);//更新最小差值
                    min_s = sum[left].i;
                    min_e = sum[right].i;
                    value = abst(sum[right].sum - sum[left].sum);
                }
                if(abst(sum[right].sum - sum[left].sum) - q > 0)
                    left++;
                else if(abst(sum[right].sum - sum[left].sum) - q < 0)
                    right++;
                else
                    break;
                if(left == right)
                    right++;
            }
            if(min_s > min_e)//因为排序可能造成left的i大于right的i,这个没关系,这样的值还是存在的,只不过前开区间就是min_e罢了,直接交换就好了
                swap(min_s, min_e);
            printf("%lld %lld %lld\n", value, min_s + 1, min_e);//注意因为是前开后闭,前开不能忘记+1
        }
    }
    return 0;
}

  

 

原文地址:https://www.cnblogs.com/jacobfun/p/12400701.html

时间: 2024-08-30 11:30:01

挑战程序设计竞赛3.2习题:Bound Found POJ - 2566的相关文章

挑战程序设计竞赛2.2习题:Allowance POJ - 3040

Allowance As a reward for record milk production, Farmer John has decided to start paying Bessie the cow a small weekly allowance. FJ has a set of coins in N (1 <= N <= 20) different denominations, where each denomination of coin evenly divides the

挑战程序设计竞赛2.2习题:Stall Reservations POJ - 3190

Stall Reservations Oh those picky N (1 <= N <= 50,000) cows! They are so picky that each one will only be milked over some precise time interval A..B (1 <= A <= B <= 1,000,000), which includes both times A and B. Obviously, FJ must create a

挑战程序设计竞赛2.3习题:Cheapest Palindrome POJ - 3280

Keeping track of all the cows can be a tricky task so Farmer John has installed a system to automate it. He has installed on each cow an electronic ID tag that the system will read as the cows pass by a scanner. Each ID tag's contents are currently a

挑战程序设计竞赛2.3习题:Making the Grade POJ - 3666

A straight dirt road connects two fields on FJ's farm, but it changes elevation more than FJ would like. His cows do not mind climbing up or down a single slope, but they are not fond of an alternating succession of hills and valleys. FJ would like t

挑战程序设计竞赛2.3习题:Cow Exhibition POJ - 2184

"Fat and docile, big and dumb, they look so stupid, they aren't muchfun..."- Cows with Guns by Dana Lyons The cows want to prove to the public that they are both smart and fun. In order to do this, Bessie has organized an exhibition that will be

挑战程序设计竞赛2.4习题:Moo University - Financial Aid POJ - 2010

Bessie noted that although humans have many universities they can attend, cows have none. To remedy this problem, she and her fellow cows formed a new university called The University of Wisconsin-Farmside,"Moo U" for short. Not wishing to admit

挑战程序设计竞赛2.6习题:X-factor Chains POJ - 3421

Given a positive integer X, an X-factor chain of length m is a sequence of integers, 1 = X0, X1, X2, …, Xm = X satisfying Xi < Xi+1 and Xi | Xi+1 where a | b means a perfectly divides into b. Now we are interested in the maximum length of X-factor ch

挑战程序设计竞赛3.1习题:Moo University - Financial Aid POJ - 2010

(原题见POJ2010) 这道题我之前采用了优先队列+预处理的方法求解(https://www.cnblogs.com/jacobfun/p/12244509.html),现在用二分的办法进行求解. 一开始我很纳闷,采用二分求解本题,如果二分的mid值不符合条件,按照二分右边界应该为mid - 1(我采用前闭后闭的二分),那么如果mid + xxx(xxx大于0)可以呢?(考虑mid不行是因为左边最小加起来大了,mid ~ mid + xxx中有极小值,使得mid + xxx的左边可以满足,那么

挑战程序设计竞赛2.3:Wooden Sticks POJ - 1065

There is a pile of n wooden sticks. The length and weight of each stick are known in advance. The sticks are to be processed by a woodworking machine in one by one fashion. It needs some time, called setup time, for the machine to prepare processing