题解:
这个题目是有两种写法的,y总在视频里只讲了list
的写法,这里我们也用STL set
写了一个。
先说一下两种写法的思路:
- 链表写法(OffLine)
其实不管是使用链表存储还是set
存储,算法的核心就是找到每一个点的前驱和后继节点,然后通过比较这两个节点和选定值差的大小关系决定使用哪一个作为最后的答案。我们假设把所有数据存入链表后进行排序,同时用一个数组记录排序后的元素在原链表中的位置是多少,我们从n
开始,找每一个节点的前后驱节点,比较后存入一个记录答案集合中,然后把这个节点删除,继续找下一个节点。这里是因为我们可以选择的元素都是在当前元素之前出现的,所以需要及时删除后来的节点。这里使用pair
实现的算法,具体见代码
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#include<bitset>
#include<queue>
#include<map>
#include<vector>
#define ll long long
#define inf -1e12
#define INF 1e12
#define ios std :: ios :: sync_with_stdio(false)
#define PII pair<ll ,ll>
using namespace std;
const int maxn = 1e5 + 10;
PII a[maxn],b[maxn],ans[maxn];
ll l[maxn],r[maxn];
map<ll ,ll> mp;
int main()
{
ios;
int n,cnt = 0;
cin >> n;
for(int i = 1;i <= n;i++) {
cin >> a[i].first;
a[i].second = i;
}
sort(a + 1,a + 1 + n);
a[0].first = inf;a[n + 1].first = INF; //加入边界便于查找
for(int i = 1;i <= n;i++){
l[i] = i - 1;r[i] = i + 1; //记录左右驱节点
mp[a[i].second] = i; //记录每个节点在排序后的位置
}
for(int i = n;i >= 2;i--){
ll j = mp[i],left = l[j],right = r[j];
// cout << left << ' ' << right << endl;
ll maxx = abs(a[j].first - a[left].first),minn = abs(a[j].first - a[right].first);
if(maxx <= minn){ //优先选择值小的
ans[++cnt].first = maxx;
ans[cnt].second = a[left].second;
}
else{
ans[++cnt].first = minn;
ans[cnt].second = a[right].second;
}
l[right] = left;r[left] = right; //删除节点
}
for(int i = cnt;i >= 1;i--) cout << ans[i].first << ' ' << ans[i].second << endl;
return 0;
}
set
做法(Online)
平衡树做法的话就直接可以使用set
,set
是一种自带排序的集合**(默认升序)**,我们就可以每输入一个值,就去查找它的前驱后继节点,其余步骤和链表写法无异。
但是需要注意的是:在set
中,s.end()
返回的是最后一个元素再后一位的指针,s.begin()
返回的是第一个元素的地址。在实现算法的时候需要注意!
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#include<bitset>
#include<queue>
#include<map>
#include<vector>
#define ll long long
#define inf -1e12
#define INF 1e12
#define ios std :: ios :: sync_with_stdio(false)
#define PII pair<ll ,ll>
using namespace std;
const int maxn = 1e5 + 19;
PII a[maxn];
set<PII> s;
int main()
{
ios;
int n,x;
cin >> n >> x;
s.insert({inf,0});
s.insert({INF,n + 1});
s.insert({x,1});
for(int i = 2;i <= n;i++) {
cin >> x;
PII sum;
ll ans = INF;
s.insert({x, i});
auto it = s.find({x,i});
if(++it != s.end() && ans > abs(it -> first - x)) {
ans = abs(it -> first - x);
sum = {ans,it -> second};
}
it--;
if(it-- != s.begin() && ans >= abs(it -> first - x)){
ans = abs(it -> first - x);
sum = {ans,it -> second};
}
cout << sum.first << ' ' << sum.second << endl;
}
return 0;
}