哈爾濱理工大學軟件與微電子學院程序設計競賽(同步賽)B.Min Value

哈爾濱理工大學軟件與微電子學院程序設計競賽(同步賽)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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章