题目大意:给一个数列,每次询问一个区间内有没有一个数出现次数超过一半。有,输出这个数,否则输出$0$
题解:主席树,查询区间第$igglfloordfrac{len+1}{2}igg floor$大,并判断它出现次数是否大于$Biglfloordfrac{len}{2}Big floor$
卡点:无
C++ Code:
#include <cstdio> #define maxn 500010 #define N (maxn * 22) int n, m; int root[maxn]; int sz[N], lc[N], rc[N], idx; void insert(int &rt, int l, int r, int num) { lc[++idx] = lc[rt], rc[idx] = rc[rt], sz[idx] = sz[rt] + 1, rt = idx; if (l == r) return ; int mid = l + r >> 1; if (num <= mid) insert(lc[rt], l, mid, num); else insert(rc[rt], mid + 1, r, num); } int query(int L, int R, int l, int r, int k, int len) { if (l == r) { if (sz[R] - sz[L] > len / 2) return l; return 0; } int mid = l + r >> 1, SZ = sz[lc[R]] - sz[lc[L]]; if (k <= SZ) return query(lc[L], lc[R], l, mid, k, len); else return query(rc[L], rc[R], mid + 1, r, k - SZ, len); } int main() { scanf("%d%d", &n, &m); for (int i = 1, x; i <= n; i++) { scanf("%d", &x); root[i] = root[i - 1]; insert(root[i], 1, n, x); } while (m --> 0) { int l, r; scanf("%d%d", &l, &r); printf("%d ", query(root[l - 1], root[r], 1, n, r - l + 2 >> 1, r - l + 1)); } return 0; }