AI智能摘要
本研究聚焦于寻找序列中重复元素的上一个出现位置,核心问题是如何高效处理大数值范围。研究采用排序方法论,通过结构体存储值与位置,将问题转化为排序后相邻元素比较。关键结论是排序结合位置记录能够精准定位重复项,时间复杂度为O(N log N)。该方法为处理大规模重复查找问题提供了有效且易于实现的解决方案,区别于基于哈希表的方案,避免了潜在的哈希冲突和内存开销。未来可探索更优的线性时间复杂度算法。
此摘要由AI分析文章内容生成,仅供参考。

[ABC378C] Repeating 题解

解题思路

我们需要为每个 ​A_i 找到它在序列 ​A 中上一次出现的位置。你可能第一想法是使用桶来进行记录当前数在此之前的位置是什么。普通的桶在这一题显然是开不了的,因为数据量达到了 ​10^9。但其实使用map进行存储也同样可以通过本题。用map的思路比较好想,在这里重点讲一下通过排序实现本题的思路。

1. 数据结构选择

首先我们需要定义一个数据结构来存储每个元素的信息,包括该元素的值和它在原序列中的位置。我们可以使用一个结构体 node,其中 v 表示元素的值,p 表示元素的原始索引位置。

2. 排序

我们将所有的元素按照它们的值进行排序。排序后,相同的值会相邻排列。这样,我们只需要在相邻的元素中检查它们是否相同,如果相同,则说明它们是重复出现的,我们可以根据排序后的位置直接找到上一个出现的位置。

3. 填充结果

在遍历排序后的数组时,若当前元素的值和前一个元素相同,那么它的结果就是前一个元素的原始位置。否则,它的结果是 ​-1

4. 时间复杂度

排序的时间复杂度是 ​O(N \log N),然后遍历一次数组来填充结果是 ​O(N)。因此,总体时间复杂度是 ​O(N \log N),这个题是完全可以pass的。

AC代码

#include<bits/stdc++.h>
#define ll long long
#define mem(x,y) memset(x,y,sizeof(x))
#define CLOSE ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int inf=0x3f3f3f3f;
const int N=2e5+5;

int n, b[N];  // b数组用来存储结果
struct node {
    int p, v;  // p为元素在原数组中的位置,v为元素的值
} a[N];

bool cmp(node a, node b) {
    if(a.v == b.v) return a.p < b.p;  // 如果值相同,按位置排序
    return a.v < b.v;  // 如果值不同,按值排序
}

int main() {
    b[0] = -1;  // 初始化b数组的第一个值为-1,作为边界值
    cin >> n;  // 输入数组长度
    for(int i = 1; i <= n; i++) {
        cin >> a[i].v;  // 输入数组元素值
        a[i].p = i;  // 记录元素的原始位置
    }
  
    sort(a + 1, a + 1 + n, cmp);  // 按值排序

    // 填充b数组
    for(int i = 1; i <= n; i++) {
        if(a[i].v == a[i - 1].v) {
            b[a[i].p] = a[i - 1].p;  // 如果当前元素与前一个相同,则B[i]为前一个位置
        } else {
            b[a[i].p] = -1;  // 否则,B[i]为-1
        }
    }

    // 输出结果
    for(int i = 1; i <= n; i++) {
        cout << b[i] << " ";  // 输出每个B[i]值
    }

    return 0;
}