博客
关于我
hdu4747 Mex(线段树)
阅读量:230 次
发布时间:2019-03-01

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

为了解决问题,我们需要计算所有子区间的mex(最小非出现的元素)之和。直接暴力枚举所有子区间是不可能的,因此我们需要一种高效的方法。

方法思路

  • 预处理

    • 预处理数组 b,其中 b[i] 表示区间 [1, i] 的mex。
    • 预处理数组 nt,其中 nt[i] 表示元素 a[i] 下一个出现的位置。
  • 线段树

    • 使用线段树来维护区间的最大值和区间和。线段树支持区间更新和查询操作。
  • 主处理

    • 对于每个左端点 i,计算右端点 jin 的所有区间的mex之和。
    • 当左端点增加时,去掉 a[1],并找到下一个出现的位置 pos。如果区间 [1, pos-1] 的最大值大于 a[1],更新相关区间的值。
  • 解决代码

    #include 
    #include
    using namespace std;#define int long longconst int maxm = 2e5 + 5;int nt[maxm];int a[maxm];int b[maxm];int n;struct Tree { int ma[maxm * 2]; int sum[maxm * 2]; int laz[maxm * 2]; inline void push(int node) { if (laz[node] != -1) { int mid = (l + r) / 2; sum[node * 2] = (mid - l + 1) * laz[node]; sum[node * 2 + 1] = (r - mid) * laz[node]; ma[node * 2] = laz[node]; ma[node * 2 + 1] = laz[node]; laz[node * 2] = laz[node]; laz[node * 2 + 1] = laz[node]; laz[node] = -1; } } inline void pop(int node, int l, int r) { if (laz[node] != -1) { int mid = (l + r) / 2; sum[node * 2] = (mid - l + 1) * laz[node]; sum[node * 2 + 1] = (r - mid) * laz[node]; ma[node * 2] = laz[node]; ma[node * 2 + 1] = laz[node]; laz[node] = -1; } } void update(int st, int ed, int val, int l, int r, int node) { if (st <= l && ed >= r) { sum[node] = (r - l + 1) * val; ma[node] = val; laz[node] = val; return; } pop(node, l, r); int mid = (l + r) / 2; if (st <= mid) { update(st, ed, val, l, mid, node * 2); } if (ed > mid) { update(st, ed, val, mid + 1, r, node * 2 + 1); } push(node); } int ask(int st, int ed, int l, int r, int node) { if (st <= l && ed >= r) { return sum[node]; } pop(node, l, r); int mid = (l + r) / 2; int ans = 0; if (st <= mid) { ans += ask(st, ed, l, mid, node * 2); } if (ed > mid) { ans += ask(st, ed, mid + 1, r, node * 2 + 1); } return ans; } int ffind(int val, int l, int r, int node) { if (ma[node] <= val) { return n + 1; } if (l == r) { return l; } pop(node, l, r); int mid = (l + r) / 2; int ans = n + 1; ans = ffind(val, l, mid, node * 2); if (ans == n + 1) { ans = ffind(val, mid + 1, r, node * 2 + 1); } return ans; } void build(int l, int r, int node) { if (l == r) { sum[node] = b[l]; ma[node] = b[l]; return; } int mid = (l + r) / 2; build(l, mid, node * 2); build(mid + 1, r, node * 2 + 1); push(node); }};int main() { ios::sync_with_stdio(0); cin.tie(0); while (cin >> n && n <= 2e5) { for (int i = 1; i <= n; ++i) { cin >> a[i]; } vector
    mark; for (int i = 1; i <= n; ++i) { mark[a[i]]++; } for (int i = 1; i <= n; ++i) { while (mark[i]) { mark[i]++; } b[i] = mark[i]; } mark.clear(); for (int i = n; i >= 1; --i) { if (mark[a[i]] == 0) { nt[i] = n + 1; } else { nt[i] = mark[a[i]]; } mark[a[i]] = i; } Tree tree; tree.build(1, n, 1); int ans = 0; for (int i = 1; i <= n; ++i) { ans += tree.ask(i, n, 1, n, 1); if (i != n) { int val = a[i]; int pos = nt[i]; int t = tree.ffind(val, 1, n, 1); if (t <= pos - 1) { tree.update(t, pos - 1, val, 1, n, 1); } } } cout << ans << endl; }}

    代码解释

  • 预处理

    • 计算数组 b,其中 b[i] 是区间 [1, i] 的mex。
    • 计算数组 nt,记录每个元素的下一个出现位置。
  • 线段树

    • 结构包含 sum(区间和)、ma(区间最大值)和 laz(懒标记)。
    • update 方法用于区间覆盖。
    • ask 方法用于区间和查询。
    • ffind 方法用于树上二分查找大于某个值的第一个位置。
    • build 方法用于树的构建。
  • 主处理

    • 遍历每个左端点 i,计算右边所有区间的mex之和。
    • 当左端点增加时,更新线段树以处理去掉元素后的mex变化。
  • 转载地址:http://ptkv.baihongyu.com/

    你可能感兴趣的文章
    Objective-C实现bfs 最短路径算法(附完整源码)
    查看>>
    Objective-C实现BF算法 (附完整源码)
    查看>>
    Objective-C实现Bilateral Filter双边滤波器算法(附完整源码)
    查看>>
    Objective-C实现binary exponentiation二进制幂运算算法(附完整源码)
    查看>>
    Objective-C实现binary search二分查找算法(附完整源码)
    查看>>
    Objective-C实现binary tree mirror二叉树镜像算法(附完整源码)
    查看>>
    Objective-C实现binary tree traversal二叉树遍历算法(附完整源码)
    查看>>
    Objective-C实现BinarySearchTreeNode树算法(附完整源码)
    查看>>
    Objective-C实现binarySearch二分查找算法(附完整源码)
    查看>>
    Objective-C实现binomial coefficient二项式系数算法(附完整源码)
    查看>>
    Objective-C实现binomial distribution二项分布算法(附完整源码)
    查看>>
    Objective-C实现bisection二分法算法(附完整源码)
    查看>>
    Objective-C实现bisection二等分算法(附完整源码)
    查看>>
    Objective-C实现BitMap算法(附完整源码)
    查看>>
    Objective-C实现bitmask位掩码算法(附完整源码)
    查看>>
    Objective-C实现bitonic sort双调排序算法(附完整源码)
    查看>>
    Objective-C实现BloomFilter布隆过滤器的算法(附完整源码)
    查看>>
    Objective-C实现BMP图像旋转180度(附完整源码)
    查看>>
    Objective-C实现bogo sort排序算法(附完整源码)
    查看>>
    Objective-C实现boruvka博鲁夫卡算法(附完整源码)
    查看>>