被束缚

链接

题目给出一串数据,比如 2 -23 44 124 -51 32 34 5 并给出目标数据t(t>0),要求我们找到一个子序列(或者一个区间),使得这个子序列的和的绝对值最接近t,并输出和的绝对值和 左区间和右区间

我们假设t为89,我们可以找到最接近的数为94,从2到5,也就是 94 2 5

这题乍一看是滑动窗口,但似乎又不太好滑,主要还是因为窗口大小未知,如果直接滑要n!次,非常大。所以我们需要找到一方法,排好序(因为原序列是乱的,往右加总和不确定),如果单调增加或单调减少,那么我们就可以减少遍历次数了

但如果直接排序的话,我们会发现得到的结果不连续(即最终区间是断开的)

解决该问题的其中一个思路是求前缀和,我们可以先求从1开始到结尾相加的和 比如 1 -2 3 -5 6 -10 其前缀和为1(1) -1(2) 2(3) -3(4) 3(5) -7(6) 括号内是编号

我们再对其进行排序 -7(6) -3(4) -1(2) 1(1) 2(3) 3(5) 我们发现右边的数减左边就是从小序号+1到大序号的和,比如(-3)-(-7)=4就是5~6的和

越是靠近右边,减去的结果越大,因为序列单调增加

思路有了,代码实现如下

#include<iostream>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
struct Node {
	int sum;
	int index;
	bool operator<(const Node& other) const {
		if (sum == other.sum) return index < other.index;
		return sum < other.sum;
	}
};
int main() {
	int n, k;
	while (cin >> n >> k && (n || k)) {
		vector<int>num(n);
		for (int i = 0;i < n;i++) {
			cin >> num[i];
		}
		vector<Node>pre(n + 1);
		pre[0] = { 0,0 };
		int sum = 0;
		for (int i = 1;i < n + 1;i++) {
			sum += num[i - 1];
			pre[i] = { sum,i };
		}
		sort(pre.begin(), pre.end());
		while (k--) {
			int t;
			cin >> t;
			int best_sum=0;
			int best_l = 0, best_r = 0, left = 0;
			int min_diff = 2e9;
			for (int right = 1;right <= n;) {
				int diff = abs(pre[right].sum - pre[left].sum);
				if (abs(diff - t) < min_diff) {
					min_diff = abs(diff - t);
					best_sum =diff;
					best_l = min(pre[left].index, pre[right].index) + 1;
					best_r = max(pre[left].index, pre[right].index);
				}
				if (diff < t) {
					right++;
				}
				else if (diff > t) {
					left++;
				}
				else {
					break;
				}
			}
			cout << best_sum<<" "<< best_l << " " << best_r << " " << endl;
		}
	}
}

时间复杂度:O(n log n + k * n)

空间复杂度:O(n)

全部评论

相关推荐

eino&nbsp;v0.7.7&nbsp;发布:新增文件系统中间件,优化序列化与反序列化,修复工具信息流问题2025年12月4日,CloudWeGo&nbsp;开源项目&nbsp;eino&nbsp;正式发布了&nbsp;v0.7.7&nbsp;版本。本次更新主要围绕文件系统中间件支持、序列化处理范围扩展、反序列化稳定性提升以及工具信息流优化进行了改进。以下是更新详情:一、支持文件系统中间件(filesystem&nbsp;middleware)在本版本中,ADK&nbsp;模块新增了对文件系统中间件的支持。这一特性使得在处理文件存储、读取、传输等场景时,能够通过中间件机制实现更加灵活、可扩展的处理逻辑,从而简化开发者在文件操作过程中的接口适配工作。二、增加序列化处理范围(serialization&nbsp;scope)持续优化&nbsp;CI&nbsp;流程的同时,这一版本扩展了序列化的处理范围,使得数据在持久化与传输过程中能够涵盖更广泛的类型与使用场景。这对大规模数据处理以及分布式环境下的任务执行具有积极作用。三、修复数组与切片反序列化异常针对反序列化环节中出现的&nbsp;checkpoint&nbsp;恢复时数组和切片解析过程中可能引发的崩溃问题,本次更新进行了修复。此改进有效提升了系统在复杂数据恢复场景下的稳定性与可靠性,减少了运行时的潜在风险。四、工具信息流中增加工具名称在&nbsp;ADK&nbsp;模块的流式工具消息(stream&nbsp;tool&nbsp;message)中,现在会附带工具名称信息。这一改动可帮助开发者在处理多工具协作或调试日志时,快速定位消息来源工具,提高问题排查与调试的效率。总结eino&nbsp;v0.7.7&nbsp;的发布为开发者带来了以下关键改进:•&nbsp;文件系统中间件支持,更好地集成文件处理逻辑•&nbsp;序列化范围扩展,适应更广泛的数据场景•&nbsp;反序列化稳定性增强,避免数组和切片解析崩溃•&nbsp;工具信息流更明确,便于调试与维护
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务