zoukankan      html  css  js  c++  java
  • 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

    题意 :给定一个长度为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: rkz2013@126.com 
      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
    ",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 }
    View Code
  • 相关阅读:
    寒假 学习进度七
    寒假学习进度
    寒假学习进度五
    寒假学习进度四
    寒假学习进度三
    寒假学习进度二
    Spark实验五
    半篇论文笔记
    REPL
    Scala基本语法及操作、程序控制结构
  • 原文地址:https://www.cnblogs.com/111qqz/p/4837019.html
Copyright © 2011-2022 走看看