POJ 2566 Bound Found

题面描述:

美国航空航天局(该机构似乎正经历叛逆期:"我就要用英尺,才不用米呢!")接收并数字化了极可能来自地外文明的信号。每个信号包含两部分:一个由n个整数值组成的序列和一个非负整数t。虽然细节不便透露,但研究人员发现信号编码了两个整数值。这两个值可以表示为序列某个子区间的下界和上界,该子区间和的绝对值最接近t。

现在给定包含n个整数的序列和非负目标值t。你需要找出序列的一个非空区间(即连续子序列),输出其起始索引l和终止索引u。要求从第l个到第u个元素(包含两端)的序列值之和的绝对值,必须比其他任何非空区间和的绝对值更接近t。

输入格式:

输入文件包含多个测试用例。每个测试用例以两个数字n和k开始。当n=k=0时输入终止。否则满足¥1≤n≤100000,随后给出构成序列的n个绝对值不超过10000的整数。接着是k个针对该序列的查询,每个查询给出一个目标值t(0≤t≤1000000000)。

输出格式:

对于每个查询,输出一行包含3个数字:最接近的绝对和值,以及实现该绝对和的某个区间的起始和终止索引。索引从1开始计数,最大不超过n。

样例:

INPUT OUTPUT
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
5 4 4
5 2 8
9 1 1
15 1 15
15 1 15

题解:

先记录数组前缀和 \(d_i\) 并将其升序排序构造单调性,使用双指针 l , r 枚举左右前缀和数组,如大于 t 则 r++ ,小于 t 则 l++ , 等于则直接Break,注意 \(d_l.id\)\(d_r.id\) 为乱序,先输出小的再输出大的。

神秘样例过不了qwq

AC CODE:

#include<iostream>
#include<algorithm>
#include<cstring>
#define int long long
using namespace std;
const int N=1e5+10;
struct node{
	int val,id;
}d[N];
int n,k,a[N];
bool cmp(node x,node y){
	return x.val<y.val;
}
signed main(){
	while(true){
		memset(d,0,sizeof(d));
		for(int i=1;i<=n;i++) d[i].val=0;
		cin>>n>>k;
		if(n==0&&k==0) break;
		for(int i=1;i<=n;i++) cin>>a[i];
		for(int i=1;i<=n;i++) d[i].val=d[i-1].val+a[i],d[i].id=i;
		sort(d,d+n+1,cmp);
		for(int i=1;i<=k;i++){
			int t;
			cin>>t;
			int minn=1e18,l=0,r=1,ansl,ansr,ans;
			while(r<=n){
				int num=d[r].val-d[l].val;
				//cout<<l<<" "<<r<<" "<<d[l].val<<" "<<d[r].val<<endl;
				if(abs(num-t)<minn) minn=abs(num-t),ans=num,ansl=d[l].id,ansr=d[r].id;
				if(num<t) r++;
				else if(num>t) l++;
				else break;
				if(l==r) r++;
			}
			if(ansl>ansr) swap(ansl,ansr);
			cout<<ans<<" "<<ansl+1<<" "<<ansr<<endl;
		}
	} 
	return 0;
}
posted @ 2025-09-11 21:22  kagmy_yzssy  阅读(46)  评论(0)    收藏  举报