算法竞赛进阶指南-50.邻值查找
题目链接
给定一个长度为 的序列 , 中的数各不相同。
对于 中的每一个数 ,求:
以及令上式取到最小值的 (记为 )。若最小值点不唯一,则选择使 较小的那个。
输入格式
第一行输入整数 ,代表序列长度。
第二行输入 个整数,代表序列的具体数值,数值之间用空格隔开。
输出格式
输出共 行,每行输出两个整数,数值之间用空格隔开。
分别表示当 取 时,对应的 和 $ P_i $ 的值。
数据范围
$n \le 10^5 |A_i| \le 10^9$
输入样例:
3
1 5 3
输出样例:
4 1
2 1
Method1 : STL-set
这题的意思就是在前面找一个与数值最接近的一个数,如果有两个数同时满足,选择的那个。
看到题目数据范围就知道不能用暴力写,要找一个的做法。
复杂度分析
- 时间复杂度:, 其中为对n进行二进制拆分的时间复杂度。
- 空间复杂度:。
Method2 : 双向链表
用链表就是离线做法:
将原数组带着下标一起,按照元素的值从小到大顺排,然后以此顺序建立双向链表,而且要从后往前考虑
#include <iostream>
#include <algorithm>
#include <limits.h>
using namespace std;
typedef pair<int, int> PII;
struct Node {
int value;
int pos;
int nxt, pre;
bool operator< (const Node& rhs) const {
return value < rhs.value;
}
};
const int N = 1e5 + 7;
int n;
Node node[N];
int head, tail, tot;
void init() {
tot = 2;
head = 1, tail = 2;
node[head].nxt = tail;
node[tail].pre = head;
}
int insert(int p, int v, int idx) {
int q = ++ tot;
node[q].value = v;
node[q].pos = idx;
node[node[p].nxt].pre = q;
node[q].nxt = node[p].nxt;
node[p].nxt = q; node[q].pre = p;
return q;
}
void remove(int p) {
node[node[p].pre].nxt = node[p].nxt;
node[node[p].nxt].pre = node[p].pre;
}
int pos[N];
PII res[N], a[N];
int main() {
init();
scanf("%d", &n);
for (int i = 1; i <= n; i ++) {
scanf("%d", &a[i].first);
a[i].second = i;
}
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i ++) {
pos[a[i].second] = insert(node[tail].pre, a[i].first, a[i].second);
}
for (int i = n; i > 1; i --) {
int s = INT_MAX, idx = -1;
Node& t = node[pos[i]];
if (t.pre != head && s > abs(t.value - node[t.pre].value)) {
s = abs(t.value - node[t.pre].value);
idx = node[t.pre].pos;
}
if (t.nxt != tail && s > abs(t.value - node[t.nxt].value)) {
s = abs(t.value - node[t.nxt].value);
idx = node[t.nxt].pos;
}
res[i] = {s, idx};
remove(pos[i]);
}
for (int i = 2; i <= n; i ++) {
printf("%d %d\n", res[i].first, res[i].second);
}
return 0;
}
复杂度分析
- 时间复杂度:, 其中为sort的时间复杂度。
- 空间复杂度:。
补一个暴力做法,会。
#include <iostream>
#include <algorithm>
#include <limits.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5 + 7;
int n;
vector<int> arr(N);
int main() {
cin >> n;
for (int i = 1; i <= n; i ++) {
scanf("%d", &arr[i]);
}
vector<PII> res;
for (int i = 2; i <= n; i ++) {
PII tmp;
tmp.first = INT_MAX;
tmp.second = i;
for (int j = i - 1; j; j --) {
int dif = abs(arr[i] - arr[j]);
if (dif < tmp.first) {
tmp.first = dif;
tmp.second = j;
}
else if (dif == tmp.first) {
if (arr[j] < arr[i]) tmp.second = j;
}
}
res.push_back(tmp);
}
for (int i = 0; i < res.size(); i ++) {
printf("%d %d\n", res[i].first, res[i].second);
}
return 0;
}
本博客所有文章均采用 CC BY-NC-SA 4.0 协议 ,禁止商用,转载请注明出处!