[BZOJ 3524] kur 绝对众数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ 3524] kur 绝对众数相关的知识,希望对你有一定的参考价值。

题意

  给定长度为 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 }

 

以上是关于[BZOJ 3524] kur 绝对众数的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ_3524_[Poi2014]Couriers_主席树

BZOJ3524: [Poi2014]Couriers

bzoj3524 Couriers

bzoj3524:[Poi2014]Couriers

BZOJ3524 [POI2014] Couriers(主席树)

[BZOJ2223][BZOJ3524][Poi2014]Couriers 主席树