zoukankan      html  css  js  c++  java
  • bzoj3524 [POI2014]Couriers

    bzoj3524 [POI2014]Couriers|$

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

    (n, mleq5 imes10^5)

    主席树


    重题 bzoj5178 /xyx

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

    时间复杂度 (O(nlog 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
    ", query(rt[l - 1], rt[r], 1, n, r - l + 1));
      }
      return 0;
    }
    
  • 相关阅读:
    mysql高并发配置
    php xml转array的方法
    双系统,一系统损坏后的解决方案之硬盘启动
    最长公共前缀
    罗马数字转整数
    回文数
    整数反转
    一、数组---两数之和
    从尾到头打印链表
    替换空格
  • 原文地址:https://www.cnblogs.com/Juanzhang/p/10624762.html
Copyright © 2011-2022 走看看