博客
关于我
E - 买礼物(链表+线段树)
阅读量:323 次
发布时间:2019-03-04

本文共 3398 字,大约阅读时间需要 11 分钟。

对于这个问题,我们可以使用一个双向链表结构来记录每个数的左右邻居,并结合并查集来维护这些邻居关系。具体来说,我们使用两个数组 LR,分别记录每个数的最左边和最右边相邻的数。这样,当删除一个数时,只需要更新它左右邻居的指针即可。

解题思路

  • 初始化邻居关系

    • 使用两个数组 LR,其中 L[i] 记录数 a[i] 的最左边相邻数的位置,R[i] 记录最右边相邻数的位置。
    • 初始化 pre 数组来维护每个数的最近访问位置。
  • 删除操作

    • 当删除一个数 a[l] 时,需要更新 L[l]R[l] 的邻居关系。
    • 特别地,链表的首尾节点需要特殊处理,当删除首尾节点时,可能会影响其邻居关系。
  • 查询操作

    • 使用树状数组(Fenwick Tree)来维护区间内的最大值。
    • 对于查询操作,查询区间 [l, r] 内是否存在两个相同的数,可以通过查找区间内的最大值 cur_max 来判断。
    • 如果 cur_max 在区间 [l, r] 内,则说明存在重复的数,输出 1;否则,输出 0
  • 代码实现细节

    #include 
    #include
    using namespace std;
    #define ENDL "\n"
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    const int maxn = 5e5 + 10;
    const int Mod = 1e9 + 7;
    int n;
    int a[maxn], L[maxn], R[maxn], pre[maxn * 2];
    int tree[maxn << 2], size = 1;
    void build(int i, int l, int r) {
    if (l == r) {
    tree[i] = R[l];
    return;
    }
    int mid = (l + r) >> 1;
    int k = i << 1;
    build(k, l, mid);
    build(k | 1, mid + 1, r);
    tree[i] = min(tree[k], tree[k | 1]);
    }
    void change(int i, int l, int r, int pos, int x) {
    if (l == r) {
    tree[i] = x;
    return;
    }
    int mid = (l + r) >> 1;
    int k = i << 1;
    if (pos <= mid) {
    change(k, l, mid, pos, x);
    } else {
    change(k | 1, mid + 1, r, pos, x);
    }
    tree[i] = min(tree[k], tree[k | 1]);
    }
    int query(int i, int l, int r, int x, int y) {
    if (l == x && r == y) {
    return tree[i];
    }
    int res = inf;
    int mid = (l + r) >> 1;
    int k = i << 1;
    if (y <= mid) {
    res = query(k, l, mid, x, y);
    } else if (x > mid) {
    res = query(k | 1, mid + 1, r, x, y);
    } else {
    int left = query(k, l, mid, x, mid);
    int right = query(k | 1, mid + 1, r, mid + 1, y);
    res = min(left, right);
    }
    return res;
    }
    int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int q;
    cin >> n >> q;
    memset(pre, inf, sizeof pre);
    for (int i = 1; i <= n; ++i) {
    cin >> a[i];
    if (pre[a[i]] != inf) {
    L[i] = pre[a[i]];
    } else {
    L[i] = inf;
    }
    pre[a[i]] = i;
    }
    pre memset to inf;
    for (int i = n; i >= 1; --i) {
    if (pre[a[i]] != inf) {
    R[i] = pre[a[i]];
    } else {
    R[i] = inf;
    }
    pre[a[i]] = i;
    }
    build(1, 1, n);
    while (q--) {
    int op;
    cin >> op;
    if (op == 1) {
    int l;
    cin >> l;
    if (L[l] != inf) {
    if (R[l] != inf) {
    int old = R[l];
    L[old] = inf;
    R[l] = inf;
    }
    if (L[l] != inf) {
    R[L[l]] = l;
    }
    if (R[l] != inf) {
    L[R[l]] = l;
    }
    }
    L[l] = R[l] = inf;
    change(1, 1, n, l, inf);
    } else {
    int l, r;
    cin >> l >> r;
    if (l > r) {
    l = r;
    }
    int cur = query(1, 1, n, l, r);
    if (cur != inf && l <= cur && cur <= r) {
    cout << "1" << ENDL;
    } else {
    cout << "0" << ENDL;
    }
    }
    }
    return 0;
    }

    代码解释

    • 初始化:使用 LR 数组记录每个数的左右邻居,pre 数组维护每个数的最近访问位置。
    • 删除操作:更新数的左右邻居关系,并使用树状数组维护区间内的最大值。
    • 查询操作:通过树状数组查找区间内的最大值,判断其是否在区间内,确定是否存在重复数。

    这种方法高效地处理了大规模数据的操作,确保了在合理时间内完成查询和删除任务。

    转载地址:http://ppqq.baihongyu.com/

    你可能感兴趣的文章
    Objective-C实现memoization优化技术算法(附完整源码)
    查看>>
    Objective-C实现memset函数功能(附完整源码)
    查看>>
    Objective-C实现merge insertion sort合并插入排序算法(附完整源码)
    查看>>
    Objective-C实现merge sort归并排序算法(附完整源码)
    查看>>
    Objective-C实现mergesort归并排序算法(附完整源码)
    查看>>
    Objective-C实现MidpointIntegration中点积分算法 (附完整源码)
    查看>>
    Objective-C实现miller rabin米勒-拉宾素性检验算法(附完整源码)
    查看>>
    Objective-C实现Miller-Rabin素性测试程序(附完整源码)
    查看>>
    Objective-C实现Miller-Rabin素性测试程序(附完整源码)
    查看>>
    Objective-C实现min cost string conversion最低成本字符串转换算法(附完整源码)
    查看>>
    Objective-C实现MinhashLSH算法(附完整源码)
    查看>>
    Objective-C实现MinhashLSH算法(附完整源码)
    查看>>
    Objective-C实现MinHeap最小堆算法(附完整源码)
    查看>>
    Objective-C实现minimum coin change最小硬币找零算法(附完整源码)
    查看>>
    Objective-C实现minimum cut最小切割流算法(附完整源码)
    查看>>
    Objective-C实现minimum partition最小分区算法(附完整源码)
    查看>>
    Objective-C实现Minimum Priority Queu最小优先级队列算法(附完整源码)
    查看>>
    Objective-C实现Minimum Vertex Cover最小顶点覆盖算法(附完整源码)
    查看>>
    Objective-C实现MinimumCostPath最小成本路径算法(附完整源码)
    查看>>
    Objective-C实现min_heap最小堆算法(附完整源码)
    查看>>