1. 程式人生 > >Bound Found [POJ2566] [尺取法]

Bound Found [POJ2566] [尺取法]

none long n) lower NPU using test seq oid

題意

給出一個整數列,求一段子序列之和最接近所給出的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 }
View Code

Bound Found [POJ2566] [尺取法]