主席树初探--BZOJ3524: [Poi2014]Couriers

n<=500000个数,m<=500000个询问,每次问区间里出现次数>(R-L+1)的数字是谁,没有输出0.

写了带修改发现不会不带修改了。。。。

不带修改的话,n个点,每个点表示一个前缀,每加入一个数时,主席树上只有logn个节点的信息,所以每次只用新建logn个节点,那前缀对应线段树里其他的信息呢?直接接到上一棵树即可。详见代码或其他博客。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<stdlib.h>
 5 //#include<iostream>
 6 using namespace std;
 7 
 8 int n,m;
 9 #define maxn 500011
10 #define maxm 10000011
11 struct SMT
12 {
13     struct Node
14     {
15         int son[2];
16         int cnt;
17     }a[maxm];
18     int size,n;
19     void clear(int m) {n=m;size=0;a[0].cnt=0;}
20     void up(int x)
21     {
22         const int &p=a[x].son[0],&q=a[x].son[1];
23         a[x].cnt=a[p].cnt+a[q].cnt;
24     }
25     void build(int pre,int &rt,int L,int R,int num)
26     {
27         rt=++size;
28         a[rt].cnt=a[pre].cnt+1;
29         if (L==R) {a[rt].son[0]=a[rt].son[1]=0;return;}
30         const int mid=(L+R)>>1;
31         if (num<=mid) build(a[pre].son[0],a[rt].son[0],L,mid,num),a[rt].son[1]=a[pre].son[1];
32         else build(a[pre].son[1],a[rt].son[1],mid+1,R,num),a[rt].son[0]=a[pre].son[0];
33     }
34     void build(int pre,int &rt,int num) {build(pre,rt,1,n,num);}
35 }smt;
36 
37 int a[maxn],b[maxn],rt[maxn],lb;
38 int main()
39 {
40     scanf("%d%d",&n,&m);
41     for (int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
42     sort(b+1,b+1+(lb=n));lb=unique(b+1,b+1+lb)-b-1;
43     for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+lb,a[i])-b;
44     
45     smt.clear(lb);
46     for (int i=1;i<=n;i++) smt.build(rt[i-1],rt[i],a[i]);
47     for (int i=1,x,y;i<=m;i++)
48     {
49         scanf("%d%d",&x,&y);x--;
50         int sa=rt[x],sb=rt[y],L=1,R=lb;bool ok=1;
51         while (L<R)
52         {
53             if (smt.a[smt.a[sb].son[0]].cnt-smt.a[smt.a[sa].son[0]].cnt>(y-x)/2)
54                 sa=smt.a[sa].son[0],sb=smt.a[sb].son[0],R=(L+R)>>1;
55             else if (smt.a[smt.a[sb].son[1]].cnt-smt.a[smt.a[sa].son[1]].cnt>(y-x)/2)
56                 sa=smt.a[sa].son[1],sb=smt.a[sb].son[1],L=((L+R)>>1)+1;
57             else {ok=0;break;}
58         }
59         if (ok) printf("%d\n",b[L]);
60         else puts("0");
61     }
62     return 0;
63 }
View Code

 

posted @ 2017-11-29 20:55  Blue233333  阅读(177)  评论(0编辑  收藏  举报