bzoj3524 [POI2014]Couriers
阿新 • • 發佈:2019-03-30
-- 樹查詢 return ack lac can 數字 答案 pri
\(\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