题意
给定长度为 n 的序列 A = {a[1], a[2], ..., a[n]} .
m 次询问, 求区间 [l, r] 的绝对众数.
n, m <= 100000 .
分析
性质1. 如果存在绝对众数, 那么中位数一定是绝对众数.
性质2. 不同数两两匹配, 最后剩下来的是绝对众数.
建立可持久化线段树, 根据 性质1 , 找中位数有多少个.
我们用 性质2 带来的摩尔投票法进行对拍.
实现
一般来说, 如果要找中位数, 都用 n+1 >> 1 , 而不是 n >> 1 , 否则当 n = 1 的时候就gg了.
AC程序:
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #define F(i, a, b) for (register int i = (a); i <= (b); i++) 6 inline int rd(void) { 7 int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; 8 int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f; 9 } 10 11 const int N = 500005; 12 const int S = 10000000; 13 14 int n, m, a[N]; 15 int rt[N], tot, Lc[S], Rc[S], cnt[S]; 16 17 #define M ((L+R)>>1) 18 inline int Insert(int x, int L, int R, int pos) { 19 int cur = ++tot; Lc[cur] = Lc[x], Rc[cur] = Rc[x], cnt[cur] = cnt[x] + 1; 20 if (L != R) 21 pos <= M ? Lc[cur] = Insert(Lc[x], L, M, pos) : Rc[cur] = Insert(Rc[x], M+1, R, pos); 22 return cur; 23 } 24 inline int Query(int x, int y, int L, int R, int K, int Siz) { 25 if (L == R) return cnt[y] - cnt[x] > Siz ? L : 0; 26 int Lsz = cnt[Lc[y]] - cnt[Lc[x]]; 27 return K <= Lsz ? Query(Lc[x], Lc[y], L, M, K, Siz) : Query(Rc[x], Rc[y], M+1, R, K - Lsz, Siz); 28 } 29 30 int main(void) { 31 #ifndef ONLINE_JUDGE 32 freopen("kur.in", "r", stdin); 33 #endif 34 35 n = rd(), m = rd(); 36 F(i, 1, n) a[i] = rd(); 37 F(i, 1, n) rt[i] = Insert(rt[i-1], 1, n, a[i]); 38 39 F(i, 1, m) { 40 int l = rd(), r = rd(); 41 printf("%d\n", Query(rt[l-1], rt[r], 1, n, (r-l+2)/2, (r-l+1)/2)); 42 } 43 44 return 0; 45 }
对拍程序:
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #define F(i, a, b) for (register int i = (a); i <= (b); i++) 6 inline int rd(void) { 7 int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; 8 int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f; 9 } 10 11 const int N = 500005; 12 13 int n, m, a[N]; 14 15 int Query(int l, int r) { 16 int key = 0, cnt = 0; 17 F(i, l, r) { 18 if (!cnt) key = a[i]; 19 if (key == a[i]) cnt++; else cnt--; 20 } 21 cnt = 0; 22 F(i, l, r) 23 cnt += (key == a[i]); 24 return cnt > (r-l+1)/2 ? key : 0; 25 } 26 27 int main(void) { 28 #ifndef ONLINE_JUDGE 29 freopen("kur.in", "r", stdin); 30 #endif 31 32 n = rd(), m = rd(); 33 F(i, 1, n) a[i] = rd(); 34 35 F(i, 1, m) { 36 int l = rd(), r = rd(); 37 printf("%d\n", Query(l, r)); 38 } 39 40 return 0; 41 }
时间: 2024-10-29 04:37:30