哈爾濱理工大學軟件與微電子學院程序設計競賽(同步賽)B.Min Value
題目描述
有一天,老師告訴多多:絕對值是指一個數在數軸上所對應點到原點的距離。
接下來老師給多多一個由 N 個數組成的序列 a1,a2,a3,······,an-1,an,他想讓多多從中任選兩個數 ai 和 aj,使得 ai + aj 的絕對值最小,並且計算出 i + j 的值,其中 i ≠ j。
由於老師給出的序列太長,多多無法完成這個任務,請你幫助他。
輸入描述:
輸入第一行包含一個正整數 N (2 ≤ N ≤ 100000)
接下來 N 行,每行一個整數 ai (1 ≤ i ≤ N,-1e6 ≤ ai ≤ 1e6)
輸出描述:
輸出兩個數,中間用空格分開,ai + aj 的絕對值的最小值和 i + j(如果有多組 i 和 j 滿足條件,輸出 i + j 最小的一組)
示例1
輸入
5
-2
6
7
7
-8
輸出
1 8
題意很簡單,我用的是最簡單暴力的方法,思路清晰,就是要考慮好幾個點~
首先用兩個數組記錄分別記錄正數和負數,然後用一個數組記錄每個數的最小的兩個下標,爲什麼是兩個,因爲如果最小的和就爲兩個該數相加,只有一個下標就相當於一個數選了兩次,顯然不符合條件,做了上述準備後計算就非常簡單,最小值無外乎以下三種情況:
1.負數數組裏面最大的兩個數
2.正數數組裏面最小的兩個數
3.對負數數組裏的數,在正數數組裏面二分查找最接近該數的數,最小值就爲兩數之和
AC代碼如下:
#include<bits/stdc++.h>
using namespace std;
int n,k,minv=2e6+5,minp=2e5+5;
map<int,pair<int,int> >m;
void judge(int x,int y){
if(abs(x+y)<minv) minv=abs(x+y),x==y?minp=m[x].first+m[x].second:minp=m[x].first+m[y].first;
if(abs(x+y)==minv) x==y?minp=min(minp,m[x].first+m[y].second):minp=min(minp,m[x].first+m[y].first);
}
main(){
cin>>n;
vector<int>v1,v2;
for(int i=1;i<=n;i++){
cin>>k;
k<0?v1.push_back(k):v2.push_back(k);
m[k].first==0?m[k].first=i:(m[k].first<i?(m[k].second==0?m[k].second=i:m[k].second=min(m[k].second,i)):m[k].first=min(m[k].first,i));
}
sort(v1.rbegin(),v1.rend());
sort(v2.begin(),v2.end());
if(v1.size()>1) judge(v1[0],v1[1]);
if(v2.size()>1) judge(v2[0],v2[1]);
for(auto i:v1){
int pos=lower_bound(v2.begin(),v2.end(),-i)-v2.begin();
if(pos==v2.size()) judge(v2.back(),i);
else{
judge(v2[pos],i);
if(pos>0) judge(v2[pos-1],i);
}
}
cout<<minv<<" "<<minp;
}