码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj3524 [POI2014]Couriers

时间:2019-03-29 23:38:19      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:poi   const   max   php   tree   mat   数字   静态   efi   

\(\verb|bzoj3524 [POI2014]Couriers|\)

静态区间,询问出现次数严格大于区间长度一半的数

\(n,\ m\leq5\times10^5\)

主席树


用主席树维护,在当前区间 \([l,\ r]\) 中,如果 \([l,\ mid]\) 的数字出现次数严格大于询问区间长度的一半,则答案必定在左子树中,递归到左子树查询;同理,如果右区间满足条件,递归到右子树查询;否则无解。

时间复杂度 \(O(n\log n)\)

代码

#include <bits/stdc++.h>
using namespace std;

#define ls(x) tree[x].l
#define rs(x) tree[x].r
#define mid ((l + r) >> 1)
const int maxn = 5e5 + 10;
int n, m, tot, a[maxn], rt[maxn];

struct node {
 int l, r, sum;
} tree[maxn * 20];

void upd(int& k, int rt, int l, int r, int pos) {
  tree[k = ++tot] = tree[rt], tree[k].sum++;
  if (l == r) return;
  if (pos <= mid) {
    upd(ls(k), ls(rt), l, mid, pos);
  } else {
    upd(rs(k), rs(rt), mid + 1, r, pos);
  }
}

int query(int p1, int p2, int l, int r, int len) {
  if (l == r) return l;
  int s1 = tree[ls(p2)].sum - tree[ls(p1)].sum;
  int s2 = tree[rs(p2)].sum - tree[rs(p1)].sum;
  if (2 * s1 > len) {
    return query(ls(p1), ls(p2), l, mid, len);
  } else if (2 * s2 > len) {
    return query(rs(p1), rs(p2), mid + 1, r, len);
  } else {
    return 0;
  }
}

int main() {
  scanf("%d %d", &n, &m);
  for (int i = 1; i <= n; i++) {
    scanf("%d", a + i);
    upd(rt[i], rt[i - 1], 1, n, a[i]);
  }
  int l, r;
  while (m--) {
    scanf("%d %d", &l, &r);
    printf("%d\n", query(rt[l - 1], rt[r], 1, n, r - l + 1));
  }
  return 0;
}

\(orz\ \color{black}{S}\color{red}{iyuan}\)

bzoj3524 [POI2014]Couriers

标签:poi   const   max   php   tree   mat   数字   静态   efi   

原文地址:https://www.cnblogs.com/Juanzhang/p/10624762.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!