主席树初探--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 }