给定一个长度为 n 的序列 A,A 中的数各不相同。对于 A 中的每一个数 A i ,求:m i n ( 1 ≤ j < i ) ∣ A i − A j ∣,以及令上式取到最小值的 j(记为 P i )。若最小值点不唯一,则选择使 A j 较小的那个。
数据范围:n<=105 ,|Ai|<=109
题解:可以借助set来实现,set的查找是O(log n)的,最终的时间复杂度大约为O(n log n)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<cmath>
#include<cstdlib>
using namespace std;
const int u=100010;
int h[u], g[3], n, m, p;
struct rec{int x,y;};
set<rec> s;
set<rec>::iterator it,lt,rt;
bool operator <(rec a,rec b)
{
return a.y<b.y;
}
bool cmp(int a,int b,int i)
{
return abs(h[a]-h[i])<abs(h[b]-h[i])||abs(h[a]-h[i])==abs(h[b]-h[i])&&h[a]<h[b];
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) scanf("%d",&h[i]);
for(int i=1;i<=n;i++)
{
rec pr; pr.x=i, pr.y=h[i];
s.insert(pr);
it=s.find(pr);//查找pr所在位置
lt=it, rt=it, m=0;
if(lt!=s.begin()) lt--,g[++m]=lt->x;//查找前驱
if(rt++,rt!=s.end()) g[++m]=rt->x; //查找后驱
if (i>=2) {
if (m<2 || cmp(g[1], g[2], i)) p=g[1]; else p=g[2];
//找到最小值的下标
printf("%d %d\n", abs(h[i]-h[p]), p);
}
}
return 0;
}