主席树入门

主席树

 

新学了个东西---主席树。。。又名可持久化线段树

主席树最基础的应用就是 第K极值。(前提是静态,动态有动态的主席树

 

首先第一大操作:建基树

主席树是 1~n 每个节点都建一颗树,节点 rt 表示的是 1~rt 的什么什么值

因为每个节点建的是值域线段树,所以要离散化(不然空间会爆)

离散好后,先建个虚拟节点 0的以这个为基准的树(我这里简称基树)。

建树过程和普通线段树差不多,分左右区间,只不过父节点与子节点的关系不再是 k<<1 和 k<<1|1,而是 dfs序。

 

接着是第二大操作:建其他树

1~n, 依次按原顺序加入节点。可因为每次操作最多只会涉及 logn 个节点,如果每个节点都建一颗线段树的话,空间可能承受不了。所以我们采用与前面树共用节点的方法。

对于那些本次操作不涉及的节点,还是用原标号(具体操作是把根节点的边直接连向原节点),对于那些涉及的点,则只能另开新节点(注意涉及到的节点对应节点的什么什么值相比前面的要更新!!!)(具体操作见代码)

 

第三大操作:查询第 k 极值

这里分两种:

1、1~i 的极值

直接查询就可以了,和平衡树、二叉排序树一样的查法,分左右两个比大小。

2、l~r 的极值

就要用到前缀和的思想。设 x= sum[r]-sum[l],则如果 k<=x 则在树的左儿子,反之则在右儿子。(其实和上面差不多,只不过要用前缀和作差)(比较抽象,可能比较难理解,自己到网上找找博客,画画图,理解理解)。

 

主席树的最基本操作基本就是这些(待填坑。。。)

 

落谷模板题:AAAAAAAAAAAAAAAA

 

贴代码:

 1 #include<bits/stdc++.h>
 2 #define mid (l+r)/2
 3 using namespace std;
 4 const int N=2e5+5;
 5 int n,q,m,cnt=0;
 6 int a[N],b[N],T[N];
 7 int sum[N<<5],L[N<<5],R[N<<5];
 8 
 9 inline int build(int l,int r)
10 {
11     int rt=++cnt;
12     sum[rt]=0;
13     if (l<r)
14     {
15         L[rt]=build(l,mid);
16         R[rt]=build(mid+1,r);
17     }
18     return rt;
19 }
20 inline int update(int lst,int l,int r,int w)
21 {
22     int rt=++cnt;
23     L[rt]=L[lst],R[rt]=R[lst]; sum[rt]=sum[lst]+1;
24     if (l<r)
25     {
26         if (w<=mid) L[rt]=update(L[lst],l,mid,w);
27         else R[rt]=update(R[lst],mid+1,r,w);
28     }
29     return rt;
30 }
31 inline int query(int u,int v,int l,int r,int k)
32 {
33     if (l>=r) return l;
34     int x=sum[L[v]]-sum[L[u]];
35     if (x>=k) return query(L[u],L[v],l,mid,k);
36     else return query(R[u],R[v],mid+1,r,k-x);
37 }
38 int main()
39 {
40     scanf("%d%d",&n,&q);
41     for (int i=1; i<=n; ++i)
42     {
43         scanf("%d",&a[i]);
44         b[i]=a[i];
45     }
46     sort(b+1,b+1+n);
47     m=unique(b+1,b+1+n)-b-1;
48     T[0]=build(1,m);
49     for (int i=1; i<=n; ++i)
50     {
51         int t=lower_bound(b+1,b+1+m,a[i])-b;
52         T[i]=update(T[i-1],1,m,t);
53     }
54     while (q--)
55     {
56         int x,y,z;
57         scanf("%d%d%d",&x,&y,&z);
58         int t=query(T[x-1],T[y],1,m,z);
59         printf("%d\n",b[t]);
60     }
61     return 0;
62 }
View Code

 

 

 

 

 

fighting fighting fighting !!!

 

posted on 2018-10-26 19:11  Frank-King  阅读(209)  评论(0编辑  收藏  举报