给定一个长度为 n 的序列 A,A 中的数各不相同。对于 A 中的每一个数 Ai,求:
min1≤j<i |Ai−Aj|
以及令上式取到最小值的 j(记为 Pi)。若最小值点不唯一,则选择使 Aj 较小的那个。
输入格式
第一行输入整数n,代表序列长度。
第二行输入n个整数A1…An,代表序列的具体数值,数值之间用空格隔开。
输出格式
输出共n-1行,每行输出两个整数,数值之间用空格隔开。
分别表示当i取2~n时,对应的min1≤j<i |Ai−Aj|和Pi的值。
数据范围
n≤10^5,|Ai|≤10^9
输入样例:
3
1 5 3
输出样例:
4 1
2 1
法1:
分析:将数列进行排序,形成链表,这样对于某一节点Ai,为使得min|Ai-Aj|达到最小,则Aj为其两个相邻节点中的一个。进行倒序处理,从n开始处理,处理完一个节点则将其从链表中删除,因为j<i,所以已经处理的节点以后就不能再用到了。pos[]用来记录节点在input[]中的位置
AC代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5+10;
pair<int,int>input[maxn],ans[maxn];
int pos[maxn],l[maxn],r[maxn];
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&input[i].first);
input[i].second=i;
}
sort(input+1,input+1+n);
for(int i=1;i<=n;i++){
l[i]=i-1,r[i]=i+1;
pos[input[i].second]=i;
}
input[0].first=-2e9,input[n+1].first=2e9;
for(int i=n;i>=2;i--){
int x=pos[i];
int leftV=input[l[x]].first,rightV=input[r[x]].first;
if(input[x].first-leftV<=rightV-input[x].first)
ans[i]={input[x].first-leftV,input[l[x]].second};
else ans[i]={rightV-input[x].first,input[r[x]].second};
l[r[x]]=l[x],r[l[x]]=r[x];
}
for(int i=2;i<=n;i++){
printf("%d %d\n",ans[i].first,ans[i].second);
}
return 0;
}
法2:
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
set<pair<int,int> >s;
int main(){
int n,x;
cin>>n>>x;
s.insert(make_pair(x,1));
for(int i=2;i<=n;i++){
pair<int,int>ans;
ans.first=0x3f3f3f3f;
cin>>x;
s.insert(make_pair(x,i));
set<pair<int,int> >::iterator it=s.find(make_pair(x,i));
if(it--!=s.begin())
ans=make_pair(x-it->first,it->second);
it=s.find(make_pair(x,i));
if(++it!=s.end()&&it->first-x<ans.first)
ans=make_pair(it->first-x,it->second);
cout<<ans.first<<" "<<ans.second<<endl;
}
return 0;
}