主席树设计与实现

主席树设计与实现

一、主席树的一句话简介

  1、主席树是可持久化线段树

  2、可持久化技术用于将多棵树相同的部分复用、不同的部分分开构成一颗新树。

  3、主席树的实际物理原型是多颗线段树。

二、区间第K大问题

  1、设计上应当考虑,如果有了多颗线段树,应当怎么做这道题?

  2、有了思路之后应当考虑,可持久化线段树的性质是什么样的,使得我们应当如何针对这种特殊的性质完成线段树的设计?

  3、如何进行更新操作?

ans:

  1、如果有多颗线段树,则每次插入新的元素建立一颗的线段树;在查找的时候,可以知道对于任意元素,有多少个元素小于等于给定元素。

  2、想象可得,每个点的更新都将造成从最底部到根节点的一系列改变。因此,可得:根节点必然每次改变,且新的更节点可以带出新的其余替换节点。

扫描二维码关注公众号,回复: 1547385 查看本文章

  3、考虑使用上一次的根节点的若干节点,在一路向下的过程中不断进行节点复制。这种写法可以相对优雅的完成主席树的更新。

题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1175

  1 #include<iostream>
  2 #include<algorithm>
  3 using namespace std;
  4 
  5 #define ll long long 
  6 #define idx(x) (lower_bound(mapp,mapp+n,x)-mapp)
  7 
  8 
  9 const ll MAXN=1<<20;
 10 
 11 int head[50233];
 12 int n,m;
 13 class Node
 14 {
 15     public:
 16         int l,r,number,lc,rc;
 17 
 18 };Node tree[MAXN];
 19 int tree_cnt ;
 20 int mapp[50233];
 21 int arr[50233];
 22 
 23 void build(int a,int b,int now)
 24 {
 25     tree_cnt ++ ;
 26     tree[now].l = a;
 27     tree[now].r = b;
 28     tree[now].number = 0;
 29     if(a == b-1)return ;
 30     int mid = (a+b)/2;
 31     tree[now].lc = tree_cnt;
 32     build(a,mid,tree_cnt);
 33     tree[now].rc = tree_cnt;
 34     build(mid,b,tree_cnt);
 35 }
 36 
 37 void insert(int pos,int key,int times,int old)
 38 {
 39         
 40     int now = tree_cnt++;
 41     int l = tree[old].l;
 42     int r = tree[old].r;
 43 
 44     tree[now].l = l;
 45     tree[now].r = r;
 46     tree[now].number = tree[old].number;
 47     if(l == r-1)
 48     {
 49         tree[now].number += key;
 50         return ;
 51     }
 52     int mid = (l+r)/2;
 53     
 54     tree[now].lc = tree[old].lc;
 55     tree[now].rc = tree[old].rc;
 56     if(pos < mid)
 57     {
 58         tree[now].lc = tree_cnt;
 59         insert(pos,key,times,tree[old].lc);
 60     }else{
 61         tree[now].rc = tree_cnt;
 62         insert(pos,key,times,tree[old].rc);
 63     }
 64     tree[now].number = tree[tree[now].lc].number + tree[tree[now].rc].number;
 65     return ;
 66 }
 67 
 68 int search(int pos,int now)
 69 {
 70     int l = tree[now].l;
 71     int r = tree[now].r;
 72     if(l == r-1)return tree[now].number;
 73     int mid = (l+r)/2;
 74     int lc = tree[now].lc;
 75     int rc = tree[now].rc;
 76     if(mid <= pos)return tree[lc].number+search(pos,rc);
 77     else return search(pos,lc);
 78 }
 79 
 80 int check(int a,int b,int num)
 81 {
 82     int cntt = search(num,head[b+1]);
 83     cntt -= search(num,head[a]);
 84     return cntt;
 85 }
 86 
 87 int bin_search(int a,int b,int l,int r,int num)
 88 {
 89     if(l == r-1)return mapp[r];
 90     int mid = (l+r)/2;
 91     int cntt = check(a,b,mid);
 92     if(cntt<num)return bin_search(a,b,mid,r,num);
 93     else return bin_search(a,b,l,mid,num);
 94 }
 95 
 96 void init()
 97 {
 98     tree_cnt = 1;
 99     head[0] = 1;
100     build(0,n,1);
101     for(int i=0;i<n;++i)
102     {
103         cin>>arr[i];
104         mapp[i] = arr[i];
105     }sort(mapp,mapp+n);
106     cin>>m;
107     for(int i=0;i<n;++i)
108     {
109         head[i+1] = tree_cnt;
110         insert(idx(arr[i]),1,i+1,head[i]);
111     }
112     for(int i=0;i<m;++i)
113     {
114         int a,b,c;
115         cin>>a>>b>>c;
116         cout<<bin_search(a,b,-1,n,b-a+2-c)<<"\n";
117     }
118 }
119 int main()
120 {
121     cin.sync_with_stdio(false);
122     while(cin>>n)init();
123     // build(0,233,1);
124 
125     return 0;
126 }
View Code

猜你喜欢

转载自www.cnblogs.com/rikka/p/9162086.html