Min Value(思维)

本文介绍了一种算法,用于找到数组中两数之和的最小绝对值,并记录下对应的元素位置。通过将正负数分开存储,利用排序和二分查找,实现了高效的求解。文章详细解释了算法步骤,包括处理正数、负数和正负数配对的情况。

题目链接:https://ac.nowcoder.com/acm/contest/5929/B
把正负数分别存起来
由于在答案相同的情况下要找序号小的,所以把每个数最小的两个序号存起来
三种情况:
1.最小的两个正数
2.最大的两个负数
3.根据每个负数寻找最接近的正数

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
int main()
{
	int n;
	scanf("%d",&n);
	vector<int> v1,v2;
	map<int,pair<int,int> >mp;
	for(int i=1;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		if(x<0) v1.push_back(x);
		else v2.push_back(x);
		if(mp[x].first==0) mp[x].first=i;
		else if(mp[x].second==0) mp[x].second=i;  		
	}
	sort(v1.rbegin(),v1.rend());
	sort(v2.begin(),v2.end());
	int ans1=0x3f3f3f3f,ans2;
	if(v1.size()>1)
	{
		if(ans1>abs(v1[0]+v1[1]))
		{
			ans1=abs(v1[0]+v1[1]);
			if(v1[0]==v1[1])
			ans2=mp[v1[0]].first+mp[v1[0]].second;
			else ans2=mp[v1[0]].first+mp[v1[1]].first;
		}
		
	}
	if(v2.size()>1)
	{
		if(ans1>abs(v2[0]+v2[1]))
		{
			ans1=abs(v2[0]+v2[1]);
			if(v2[0]==v2[1])
			ans2=mp[v2[0]].first+mp[v2[0]].second;
			else ans2=mp[v2[0]].first+mp[v2[1]].first;
		}
		else  if(ans1==abs(v2[0]+v2[1]))
		{
			if(v2[0]==v2[1])
			ans2=min(ans2,mp[v2[0]].first+mp[v2[0]].second);
			else ans2=min(ans2,mp[v2[0]].first+mp[v2[1]].first);
		}
	
	}
	if(v1.size()>0&&v2.size()>0)
	{
		int len=v1.size();
		for(int i=0;i<len;i++)
		{
		    //小于等于(这两个函数要求数组从小到大)
			int x=upper_bound(v2.begin(),v2.end(),-v1[i])-v2.begin()-1;
			//大于等于
			int y=lower_bound(v2.begin(),v2.end(),-v1[i])-v2.begin();
			if(x>=0&&x<v2.size()) 
			{
				if(ans1>abs(v1[i]+v2[x]))
				{
					ans1=abs(v1[i]+v2[x]);
					ans2=mp[v1[i]].first+mp[v2[x]].first;
				}
				else  if(ans1==abs(v1[i]+v2[x]))
				{
				    ans2=min(ans2,mp[v1[i]].first+mp[v2[x]].first);
				}
			}
			if(y>=0&&y<v2.size())
			{
				if(ans1>abs(v1[i]+v2[y]))
				{
					ans1=abs(v1[i]+v2[y]);
					ans2=mp[v1[i]].first+mp[v2[y]].first;
				}
				else  if(ans1==abs(v1[i]+v2[y]))
				{
				    ans2=min(ans2,mp[v1[i]].first+mp[v2[y]].first);
				}
			}
		}
	}
	printf("%d %d\n",ans1,ans2);
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值