Chairman of the tree [weight] && example segment tree K-th Number POJ - 2104

First, the President of the trees and the weight difference between the tree line

Chairman of the tree is composed of many tree line weights, individual weights segment tree can only be solved to find the entire range of k large / small-value problem (what is the whole interval, such as you interval [1,8] to establish a corresponding weight value segment tree, then you can not ask the interval [2,5] k-large / small value, you can only ask [1,8] k-big / small-value problem)

 

Second, what is the right value segment tree ghost

Before learning segment tree weights you certainly want to know that tree line, tree line is the number of all sections of maintenance

Weight segment tree maintenance object and its different weights <==> the number of times this number appears in this interval

For example 1,5,3,2,4

The right to establish the value of the tree line:

 

 You will find that the weight of the tree line and the establishment of different tree line, tree line to consider the position of each number in the interval

But the tree line do not control the weight, the equivalent of a tree after drained established order. To note: the weights on behalf of this number there have been several

 

For example: We are looking for the third small interval of values

We judge from the root [1,5] of the left node, because the weight of the left node is greater than 3, so the first 3 small value within the interval certainly at the root node in the left section

We look at the interval [1,3] of the left node, found that it is the right of the left node 2 is less than 3, so the answer is certainly in the interval [1,3] to the right node. Note: this time we are looking for 3-2 small value in the right node

After that first small range of values ​​[3,3] 3 itself it is certainly within the

 

If you pay attention to the topic of data is particularly large, such as 1,1000,200000000 these three numbers, but if we built directly weights tree line, that memory on the bombing

So this time we should discretization

 

Third, the President of the trees make

We said at the beginning of the article, the Chairman of the tree is composed of many weights tree line, and Chairman of the tree can be resolved: the corresponding interval established by the President tree, you can find the k large / small values ​​within the interval of all sub-sections

(Ie, the interval [1,5] Chairman established tree, then we can look for the interval [1,3] k-large / small value)

1, Resolution 1:

After sorting to find the location of the output (do not want a violent methods will certainly be card)

2. Solution 2:

For an interval [l, r] we appeared with a number within this range with the composition of a number of weights tree line, then the query gets the job done

But repeatedly asked a small range of k, so every time we build a tree line, so that not only the spatial complexity is very high, and the time complexity is very high, even higher than the ordinary sort, then we just can not think of a way, such that for each of us for different intervals we do not need to re-contribution, if so. Time complexity and space complexity is greatly reduced.

3. Solution 3:

This uses prefixes and , for example, we have a problem. Each time interval is static and seek, so we can pre-prefix and the sum [i], every time we solve the interval [l, r] and when we can get the answer directly to sum [r] - sum [l - 1], so that no number for each interval are summed to solved. (Here we set SUM [i] is the weight of the discharge line weights tree node i)

 

Expect to write up

We can interval [1,5] Create segment tree weights 6, namely, [0,0], [1,1], [1,2], [1,3], [1,4], [ 1,5] ([0,0] is an empty tree)

We will deal with an arbitrary interval [l, r] can pass when the processing interval [1, l - 1], [1, r], on the line, and then processing results are summed two line subtraction. Why meet nature of addition and subtraction, we can easily draw a simple analysis. If [1, l - 1] x in the interval with a number less than a number, in [1, r] y is less than the number that has a number, then in the interval [l, r] y in there - the number of x less than that number, so you can well understand why the addition and subtraction, addition, and every single tree structure are the same, is a leaf node is n the tree line.

 

Above using the prefix and the idea is just to solve the problem of the complexity of the time, it does not solve the problem of space complexity, space complexity to solve the problem. We need to use the property line of the tree, every time we update a number, then compared with the previous update, the Fengyun tree line change just one chain (from the root node to a leaf node), then we can take advantage of this feature, because of the tree than the first particles i i- 1 pieces tree, simply updates the i th element, then the particles in fact, between the i and i-1 th tree tree particles only log node information is different. So the two trees have a lot of the same node, the two trees may share many nodes, i.e., a node we insert a [i] in the i-1 th tree obtained i-th particle weight particle segment tree , and a single point of insertion process only modifies that log on the root node to the leaf nodes of the path. So this would resolve the problem of the space complex.

 

1,3,2,5,4 or in the above as an example:

1, the beginning of an empty tree

 

2, node 1 plus a

 

 

3, plus a 2 node

 

 

 

 4, adding a node 3

 

 

 Behind No. 4 and 5 nodes do not write, you know on the line. . .

 

Fourth, the President of the complexity of the tree

Insert a point in space and time complexity are O (log n), so the establishment of the President of the Fengyun tree tree line [weight] of the overall complexity of time and space is O (n log n), a single inquiry after log n nodes, time complexity is also O (log n)

 

5, example

K-th Number  POJ - 2104

 

Code 1:

 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<string.h>
 5 using namespace std;
 6 const int maxn=1e5+10;
 7 int cnt,ranks[maxn],v[maxn],root[maxn];
 8 struct shudui
 9 {
10     int value,id;
11 }w[maxn];
12 struct Node
13 {
14     int l,r,sum;
15     Node(){
16         sum=0;
17     }
18 }tree[maxn*20];
19 bool mmp(shudui x,shudui y)
20 {
21     return x.value<y.value;
22 }
23 void init()
24 {
25     cnt=1;
26     root[0]=0;
27     tree[0].l=tree[0].r=tree[0].sum=0;
28 }
29 void inserts(int num,int &rt,int l,int r)
30 {
31     tree[cnt++]=tree[rt];
32     rt=cnt-1;
33     tree[rt].sum++;
34     if(l==r) return;
35     int mid=(l+r)>>1;
36     if(num<=mid) inserts(num,tree[rt].l,l,mid);
37     else inserts(num,tree[rt].r,mid+1,r);
38 }
39 int query(int i,int j,int k,int l,int r)
40 {
41     int d=tree[tree[j].l].sum-tree[tree[i].l].sum;
42     if(l==r) return l;
43     int mid=(l+r)>>1;
44     if(k <= d) return query(tree[i].l, tree[j].l, k, l, mid);  //这里是小写的L,mid可不是数字1
45     else return query(tree[i].r, tree[j].r, k - d, mid + 1, r);
46 }
47 int main()
48 {
49     int n,m;
50     scanf("%d%d",&n,&m);
51     for(int i=1;i<=n;++i)
52     {
53         scanf("%d",&w[i].value);
54         w[i].id=i;
55     }
56     sort(w+1,w+1+n,mmp);
57     w[0].value=-1;
58     int j=1;
59     for(int i=1;i<=n;++i)
60     {
61         if(w[i].value!=w[i-1].value)
62             ranks[w[i].id]=j,v[j]=w[i].value,j++;
63         else ranks[w[i].id]=j-1;
64     }
65     init();
66     for(int i=1;i<=n;++i)
67     {
68         //printf("%d %d\n",ranks[i],v[i]);
69         root[i]=root[i-1];
70         inserts(ranks[i],root[i],1,n);
71     }
72     while(m--)
73     {
74         int l,r,x;
75         scanf("%d%d%d",&l,&r,&x);
76         printf("%d\n",v[query(root[l-1],root[r],x,1,n)]);
77     }
78     return 0;
79 }

 

代码2:

  1 //洛谷 P3834 可持久化线段树(主席树)
  2 
  3 #include<cstdio>
  4 
  5 #include<cstring>
  6 
  7 #include<algorithm>
  8 
  9 using namespace std;
 10 
 11 const int N=200005;
 12 
 13 int n,m,q,t=0;
 14 
 15 int a[N],b[N],root[N];
 16 
 17 struct node
 18 
 19 {
 20 
 21     int ls,rs,sum;
 22 
 23 }tree[N*20];
 24 
 25 void disc()
 26 
 27 {
 28 
 29     int i;
 30 
 31     sort(b+1,b+n+1);
 32 
 33     m=unique(b+1,b+n+1)-(b+1);
 34 
 35     for(i=1;i<=n;++i)
 36 
 37       a[i]=lower_bound(b+1,b+m+1,a[i])-b;
 38 
 39 }
 40 
 41  
 42 
 43 //insert函数就是说:当前插入的数p,会影响节点x,所以把x节点的sum加1.
 44 
 45  
 46 
 47 //节点x代表一个权值区间,影响x就是说p在节点x所代表的权值区间内。
 48 
 49 //那么先把前一个树的对应区间的节点复制过来,再加1,就行了。
 50 
 51 //可以结合刚才的图感性理解一下。
 52 
 53 void insert(int y,int &x,int l,int r,int p)
 54 
 55 {
 56 
 57     x=++t;    //t相当于是一个节点的地址,每个节点是不同的。
 58 
 59     tree[x]=tree[y];    //复制前一个树的对应节点【它们代表的权值区间相同】。
 60 
 61     tree[x].sum++;      //给这个节点的sum加1.(这个1指的就是p)
 62 
 63     if(l==r)  return;   //搜索到根节点就返回。
 64 
 65     int mid=(l+r)>>1;
 66 
 67  
 68 
 69     //判断在哪个区间继续插入。
 70 
 71     if(p<=mid)  insert(tree[y].ls,tree[x].ls,l,mid,p);
 72 
 73     else  insert(tree[y].rs,tree[x].rs,mid+1,r,p);
 74 
 75 }
 76 
 77  
 78 
 79 //k是查询第k小
 80 
 81 //x和y相当于是树的节点的地址。而l和r就是这两个节点的权值区间。
 82 
 83 //一开始query(root[l-1],root[r],1,m,k)。
 84 
 85 //root[l-1]就是第l-1颗树的根节点。root[r]就是第r颗树的根节点。
 86 
 87 //比较它们左儿子代表的区间中的数的个数,差值为delta。根据delta判断这两个节点一起往哪个方向跳。
 88 
 89 //分析过程和刚才二分的过程一样。
 90 
 91 int query(int x,int y,int l,int r,int k)
 92 
 93 {
 94 
 95     if(l==r)  return l;    //查到权值线段树的叶子节点就返回这个值。
 96 
 97     int delta=tree[tree[y].ls].sum-tree[tree[x].ls].sum;
 98 
 99     int mid=(l+r)>>1;
100 
101     if(k<=delta)  return query(tree[x].ls,tree[y].ls,l,mid,k);
102 
103     else  return query(tree[x].rs,tree[y].rs,mid+1,r,k-delta);
104 
105 }
106 
107 int main()
108 
109 {
110 
111     int l,r,i,k;
112 
113     scanf("%d%d",&n,&q);
114 
115     for(i=1;i<=n;++i)
116 
117     {
118 
119         scanf("%d",&a[i]);
120 
121         b[i]=a[i];
122 
123     }
124 
125     disc();
126 
127     for(i=1;i<=n;++i)
128 
129       insert(root[i-1],root[i],1,m,a[i]);
130 
131     for(i=1;i<=q;++i)
132 
133     {
134 
135         scanf("%d%d%d",&l,&r,&k);
136 
137  
138 
139         //query函数返回的是第k小的权值。
140 
141         //把这个权值转化为原来这个权值对应的数就行了。
142 
143         printf("%d\n",b[query(root[l-1],root[r],1,m,k)]);
144 
145     }
146 
147     return 0;
148 
149 }

 

参考博客:

https://blog.csdn.net/g21glf/article/details/82986968

https://blog.csdn.net/creatorx/article/details/75446472

Guess you like

Origin www.cnblogs.com/kongbursi-2292702937/p/12059072.html