【主席树】bzoj3524: [Poi2014]Couriers

主席树 上 二分(和线段树上二分一个道理的单支log

Description

给一个长度为n的序列a。1≤a[i]≤n。
m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。

Input

第一行两个数n,m。
第二行n个数,a[i]。
接下来m行,每行两个数l,r,表示询问[l,r]这个区间。

Output

m行,每行对应一个答案。


题目分析

线段树 上 二分的一个简单应用。

有些时候就是把套二分做成上二分,少一只log

 1 #include<bits/stdc++.h>
 2 const int maxn = 500035;
 3 const int maxNode = 12000035;
 4 
 5 struct node
 6 {
 7     int val,l,r;
 8 }a[maxNode];
 9 int n,m,tot,rt[maxn],w[maxn],cnt[maxn];
10 
11 int read()
12 {
13     char ch = getchar();
14     int num = 0, fl = 1;
15     for (; !isdigit(ch); ch=getchar())
16         if (ch=='-') fl = -1;
17     for (; isdigit(ch); ch=getchar())
18         num = (num<<1)+(num<<3)+ch-48;
19     return num*fl;
20 }
21 void build(int &rt, int l, int r)
22 {
23     rt = ++tot;
24     if (l==r) return;
25     int mid = (l+r)>>1;
26     build(a[rt].l, l, mid);
27     build(a[rt].r, mid+1, r);
28 }
29 void update(int pre, int &rt, int l, int r, int c)
30 {
31     rt = ++tot, a[rt] = a[pre], ++a[rt].val;
32     if (l==r) return;
33     int mid = (l+r)>>1;
34     if (c <= mid) update(a[pre].l, a[rt].l, l, mid, c);
35     else update(a[pre].r, a[rt].r, mid+1, r, c);
36 }
37 int query(int L, int R)
38 {
39     int l = 1, r = cnt[0], x = rt[L-1], y = rt[R], lim = (R-L+1)>>1, mid;
40     while (l!=r)
41     {
42         mid = (l+r)>>1;
43         if (a[y].val-a[x].val <= lim) return 0;
44         if (a[a[y].l].val-a[a[x].l].val > lim)
45             r = mid, x = a[x].l, y = a[y].l;
46         else if (a[a[y].r].val-a[a[x].r].val > lim)
47             l = mid+1, x = a[x].r, y = a[y].r;
48         else return 0;
49     }
50     return cnt[l];
51 }
52 void write(int x){if (x/10) write(x/10);putchar(x%10+'0');}
53 int main()
54 {
55     n = read(), m = read();
56     for (int i=1; i<=n; i++) cnt[i] = w[i] = read();
57     std::sort(cnt+1, cnt+n+1);
58     cnt[0] = std::unique(cnt+1, cnt+n+1)-cnt-1;
59     build(rt[0], 1, n);
60     for (int i=1; i<=n; i++)
61     {
62         w[i] = std::lower_bound(cnt+1, cnt+cnt[0]+1, w[i])-cnt;
63         update(rt[i-1], rt[i], 1, cnt[0], w[i]);
64     }
65     for (int i=1; i<=m; i++)
66     {
67         int l = read(), r = read();
68         write(query(l, r)), putchar('\n');
69     }
70     return 0;
71 }

 

 

END

posted @ 2019-01-10 18:15  AntiQuality  阅读(115)  评论(0编辑  收藏  举报