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

http://poj.org/problem?id=2566;

Bound Found
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 2237   Accepted: 692   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

题意:找连续的串,求和绝对值与所给数字最接近的串。

思路:先求下标为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 #include<stdio.h>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<string.h>
  5 #include<math.h>
  6 #include<vector>
  7 #include<map>
  8 #include<stack>
  9 int cmp(const void*p,const void*q);
 10 typedef struct pp
 11 {
 12     int cost ;
 13     int x;
 14     int y;
 15 } ss;
 16 const int N=1<<30;
 17 const int M=1e6;
 18 int a[M];
 19 int b[M];
 20 ss dp[M];
 21 using namespace std;
 22 int main(void)
 23 {
 24     int n,i,j,k,p,q;
 25     while(scanf("%d %d",&p,&q),p!=0&&q!=0)
 26     {
 27         for(i=1; i<=p; i++)
 28         {
 29             scanf("%d",&a[i]);
 30         }
 31         dp[1].cost=a[1];
 32         dp[1].x=1;
 33         dp[1].y=1;
 34         for(i=2; i<=p; i++)
 35         {
 36             dp[i].cost=a[i]+dp[i-1].cost;
 37             dp[i].x=1;
 38             dp[i].y=i;
 39         }
 40         qsort(dp+1,p,sizeof(ss),cmp);
 41         while(q--)
 42         {
 43             scanf("%d",&k);
 44             int ll=1;
 45             int rr=1;
 46             int minn=N;
 47             int lb;
 48             int rb;
 49             int co;
 50             for(i=1; i<=p; i++)
 51             {
 52                 if(abs(abs(dp[i].cost)-k)<minn)
 53                 {
 54                     minn=abs(abs(dp[i].cost)-k);
 55                     lb=1;
 56                     rb=dp[i].y;
 57                     co=abs(abs(dp[i].cost));
 58                 }
 59             }
 60             while(rr<p)
 61             {
 62                 while(rr<=p&&abs(dp[rr].cost-dp[ll].cost)<=k)
 63                 {
 64                     rr++;
 65                 }
 66                 if(rr==p+1)
 67                 {
 68                     rr--;
 69                 }
 70                 if(abs(dp[rr].cost-dp[ll].cost)>k&&rr-ll>1)
 71                 {
 72                     int nx=abs(abs(dp[rr].cost-dp[ll].cost)-k);
 73                     int ny=abs(abs(dp[rr-1].cost-dp[ll].cost)-k);
 74                     int kl=rr;
 75                     if(ny<nx)
 76                     {
 77                         kl--;
 78                     }
 79                     if(abs(abs(dp[kl].cost-dp[ll].cost)-k)<minn)
 80                     {
 81                         lb=min(dp[kl].y,dp[ll].y)+1;
 82                         rb=max(dp[kl].y,dp[ll].y);
 83                         minn=abs(abs(dp[kl].cost-dp[ll].cost)-k);
 84                         co=abs(dp[kl].cost-dp[ll].cost);
 85                     }
 86                 }
 87                 else if(abs(dp[rr].cost-dp[ll].cost)>k&&rr-ll==1)
 88                 {
 89                     if(abs(abs(dp[rr].cost-dp[ll].cost)-k)<minn)
 90                     {
 91                         lb=min(dp[rr].y,dp[ll].y)+1;
 92                         rb=max(dp[rr].y,dp[ll].y);
 93                         minn=abs(abs(dp[rr].cost-dp[ll].cost)-k);
 94                         co=abs(dp[rr].cost-dp[ll].cost);
 95                     }
 96 
 97                 }
 98                 else if(abs(dp[rr].cost-dp[ll].cost)<=k)
 99                 {
100                     if(abs(abs(dp[rr].cost-dp[ll].cost)-k)<minn)
101                     {
102                         lb=min(dp[rr].y,dp[ll].y)+1;
103                         rb=max(dp[rr].y,dp[ll].y);
104                         minn=abs(abs(dp[rr].cost-dp[ll].cost)-k);
105                         co=abs(dp[rr].cost-dp[ll].cost);
106                     }
107 
108                 }
109                 ll++;
110             }
111             printf("%d %d %d\n",co,lb,rb);
112         }
113     }
114 }
115 int cmp(const void*p,const void*q)
116 {
117     ss*ww=(ss*)p;
118     ss*w=(ss*)q;
119     if(ww->cost==w->cost)
120     {
121         return  ww->y-w->y;
122     }
123     return ww->cost-w->cost;
124 }

 二分

  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<stdlib.h>
  4 #include<string.h>
  5 #include<algorithm>
  6 #include<iostream>
  7 #include<map>
  8 const int N=1000000;
  9 int cmp(const void*p,const void*q);
 10 int er(int n,int m,int t,int c);
 11 typedef struct pp
 12 {
 13     int cost;
 14     int le;
 15     int ri;
 16 } ss;//结构体记录前缀数组和和其左右端点
 17 ss a[N];
 18 int b[N],c[N];
 19 int  vv;
 20 using namespace std;
 21 int main(void)
 22 {
 23     int n,i,j,k,p,q;
 24     while(scanf("%d %d",&p,&q),p!=0&&q!=0)
 25     {
 26         for(i=1; i<=p; i++)
 27             scanf("%d",&b[i]);
 28         int cnt=1;
 29         a[cnt].cost=b[1];
 30         a[cnt].le=1;
 31         a[cnt].ri=1;
 32         cnt++;
 33         for(i=2; i<=p; i++)
 34         {
 35             a[cnt].cost=a[cnt-1].cost+b[i];
 36             a[cnt].le=1;
 37             a[cnt].ri=i;
 38             cnt++;
 39         }
 40         qsort(a+1,cnt-1,sizeof(ss),cmp);
 41         /*for(i=1;i<=p;i++)
 42         {
 43             printf("%d\n",a[i].cost);
 44             printf("000\n");
 45             printf("%d\n",a[i].ri);
 46         }*/
 47         for(i=1; i<=q; i++)
 48         {
 49             cin>>b[i];
 50         }
 51         for(int pq=1; pq<=q; pq++)
 52         {
 53             k=b[pq];
 54             int minn=1<<30;
 55             int ll=0;
 56             int rr=0;
 57             int uk=0;
 58             for(j=1; j<=p; j++)
 59             {
 60                 if(abs(abs(a[j].cost)-k)<minn)
 61                 {
 62                     minn=abs(abs(a[j].cost)-k);
 63                     uk=abs(a[j].cost);
 64                     ll=1;
 65                     rr=a[j].ri;
 66                 }
 67             }//首先把所有前缀过一遍更新最小,因为二分时找不到
 68             for(j=1; j<p; j++)
 69             {
 70                 int kk=er(j+1,p,k,j);
 71                 vv=j;
 72                 if(kk==p)
 73                 {if(kk-vv>1)//这里需要判断下,kk-vv>1才能用下面的比较。
 74                     {int uu=abs(abs(a[kk-1].cost-a[j].cost)-k);
 75                     int w=abs(abs(a[kk].cost-a[j].cost)-k);
 76                     if(uu<w)
 77                     {
 78                         kk--;
 79                     }
 80                     int ww=abs(abs(a[kk].cost-a[j].cost)-k);
 81                     if(ww<minn)
 82                     {
 83                         minn=ww;
 84                         ll=min(a[kk].ri,a[j].ri)+1;
 85                         rr=max(a[kk].ri,a[j].ri);
 86                         uk=abs(a[kk].cost-a[j].cost);
 87                     }}
 88                     else if(kk-vv==1)//kk-vv正好为1时表明kk就为所找,不能再比较kk-1,因为kk-1为空值
 89                     { int ww=abs(abs(a[kk].cost-a[j].cost)-k);
 90                     if(ww<minn)
 91                     {
 92                         minn=ww;
 93                         ll=min(a[kk].ri,a[j].ri)+1;
 94                         rr=max(a[kk].ri,a[j].ri);
 95                         uk=abs(a[kk].cost-a[j].cost);
 96                     }
 97                     }
 98                 }
 99                 else
100                 {
101 
102                     int uu=abs(abs(a[kk-1].cost-a[j].cost)-k);
103                     int w=abs(abs(a[kk].cost-a[j].cost)-k);
104                     if(uu<w)
105                     {
106                         kk--;
107                     }
108                     if(kk==j)
109                     {
110                         kk++;
111                     }
112                     int ww=abs(abs(a[kk].cost-a[j].cost)-k);
113                     if(ww<minn)
114                     {
115                         minn=ww;
116                         ll=min(a[kk].ri,a[j].ri)+1;
117                         rr=max(a[kk].ri,a[j].ri);
118                         uk=abs(a[kk].cost-a[j].cost);
119 
120                     }
121                 }
122 
123             }
124             printf("%d %d %d\n",uk,ll,rr);
125         }
126     }
127 }
128 int cmp(const void*p,const void*q)//二分查找
129 {
130     ss*w=(ss*)p;
131     ss*ww=(ss*)q;
132     return w->cost-ww->cost;
133 }
134 int er(int n,int m,int k,int c)
135 {
136     int y=(n+m)/2;
137     if(abs(a[y].cost-a[c].cost)==k)
138     {
139         return y;
140     }
141     else if(n==m)
142     {
143         return m;
144     }
145     else if(abs(a[y].cost-a[c].cost)>k&&abs(a[y-1].cost-a[c].cost)<k)
146     {
147         return y;
148     }
149     else if(abs(a[y].cost-a[c].cost)<k&&abs(a[y-1].cost-a[c].cost)<k)
150     {
151         return er(y+1,m,k,c);
152     }
153     else return er(n,y-1,k,c);
154 }

 

你可能感兴趣的:(poj 2566Bound Found(前缀和,尺取法))