Frequent values POJ - 3368(线段树)
发布日期:2021-05-10 20:50:09 浏览次数:19 分类:精选文章

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

为了解决这个问题,我们需要处理一个已经按非降序排列的数组,并对多个查询请求返回每个查询区间内出现次数最多的数的次数。

方法思路

为了高效处理这个问题,我们使用线段树来存储每个区间内出现次数最多的数的次数。具体步骤如下:

  • 预处理数组:构建一个数组b,其中b[i]记录的是从数组开头到第i个元素的连续相同数的出现次数。
  • 构建线段树:使用线段树来存储区间内的最大值。每个节点存储对应区间内的最大出现次数。
  • 处理查询:对于每个查询,确定查询区间的起始点cot,然后查询线段树返回该区间内出现次数最多的数的次数。
  • 解决代码

    #include 
    #include
    #include
    using namespace std;int n, q;int a[100001], b[100001];int tree[200002];void build(int x, int l, int r) { if (l == r) { tree[x] = b[l]; return; } int mid = (l + r) / 2; build(x * 2, l, mid); build(x * 2 + 1, mid + 1, r); tree[x] = max(tree[x * 2], tree[x * 2 + 1]);}int query(int s, int t, int l, int r, int x) { if (s > r || t < l) { return -1; } if (s <= l && r <= t) { return tree[x]; } int mid = (l + r) / 2; int left = query(s, t, l, mid, x * 2); int right = query(s, t, mid + 1, r, x * 2 + 1); return max(left, right);}int main() { while (true) { scanf("%d", &n); if (n == 0) break; scanf("%d", &q); fill(b, b + n + 1, 1); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); if (i > 1 && a[i] == a[i - 1]) { b[i] = b[i - 1] + 1; } else { b[i] = 1; } } build(1, 1, n); for (int i = 0; i < q; ++i) { int s, t; scanf("%d %d", &s, &t); int cot = s; while (cot <= t) { if (cot > 1 && a[cot] == a[cot - 1]) { cot++; } else { break; } } int max_val = query(cot, t, 1, n, 1); if (max_val == -1) { cout << 0 << endl; } else { cout << max_val << endl; } } } return 0;}

    代码解释

  • 预处理数组:读取输入并构建数组b,其中b[i]记录从数组开头到第i个元素的连续相同数的出现次数。
  • 构建线段树:线段树的每个节点存储对应区间内的最大值。叶子节点对应数组中的元素,内部节点通过合并左右子节点的信息得到最大值。
  • 处理查询:对于每个查询,确定查询区间的起始点cot,然后查询线段树返回该区间内出现次数最多的数的次数。
  • 上一篇:cf1343D(差分数组)
    下一篇:线段树的两种表示(收藏)

    发表评论

    最新留言

    哈哈,博客排版真的漂亮呢~
    [***.90.31.176]2025年05月07日 03时43分00秒