Chairman of the tree shallow learning

Before learning the Chairman of the tree without modification, and today I want to learn about the Chairman of the tree to be modified. Prior to revisit this tree a bit Chairman, President tree has a new understanding.

Chairman of the tree is actually a historical record of every version of the tree, so this space to open a large, usually open 40 times is enough.

First, to build an empty tree, then we ask for the number of discretization, the last is updated each time a new tree.

Learning Address

void build(int &id,int l,int r)
{
    id = ++tot;
    sum[id] = 0;
    int mid = (l + r) >> 1;
    if (l == r) return;
    build(lc[id], l, mid);
    build(rc[id], mid + 1, r);
}

 

During each new achievements in the sum ++ this is well understood, because we put a point into it, so the new trees after inheriting the original information to +1

The weights on the line and a bit like a tree. This is an update operation

Update int (ID int, int L, R & lt int, int Val) 
{ 
	int TOT RT = ++; 
	SUM [RT] = SUM [ID] +. 1; 
	LC [RT] = LC [ID], RC [RT] = RC [ID]; 
	IF (R & lt == L) return RT; 
	int MID = (L + R & lt) >>. 1; 
	IF (Val <= MID) LC [RT] = Update (LC [RT], L, MID, val); // if we want to put this number is smaller than the mid, go out into the small side update 
	else rc [rt] = update ( rc [rt], mid + 1, r, val); // to the contrary is a big update here. 
	RT return; 
}

  

I think it is more difficult to write the query

int query (int u, int v , int l, int r, int k) // u is the first segment, v is the second segment 
{ 
	int MID = (L + R & lt) >>. 1; 
	int X = SUM [lc [u]] - sum [lc [v]]; // sum subtraction represents the number inside this interval 
	if (l == r) return l ; // l == r if it reaches a leaf node Description found 
	if (k <= x) return query (lc [u], lc [v], l, mid, k); // if a small number of large k than the left section, then the interval left 
	return query (rc [u], rc [ v], mid + 1, r, k - x); // if in the right range, then it should be left by subtracting the number of sections 
} // this sum is in fact stored number, we seek to find the k-th largest in fact, what this period is the interval of the k-number, if in the right range, then it should be the right section of the k-sum [] large

  

This topic Link to K-th Number

 

Overall Code

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
#include <map>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
int root[maxn * 40], lc[maxn * 40], rc[maxn * 40], sum[maxn * 40];
int tot = 0;

void build(int &id,int l,int r)
{
    id = ++tot;
    sum[id] = 0;
    int mid = (l + r) >> 1;
    if (l == r) return;
    build(lc[id], l, mid);
    build(rc[id], mid + 1, r);
}

int update(int id,int l,intR & lt, int Val) 
{ 
    int RT = ++ TOT; 
    SUM [RT] = SUM [ID] + . 1 ; 
    LC [RT] = LC [ID], RC [RT] = RC [ID];
     IF (L == R & lt) return RT;
     int MID = (L + R & lt) >> . 1 ;
     IF (Val <= MID) LC [RT] = Update (LC [RT], L, MID, Val); // if we want to put in this mid smaller than this number, go out into the small side updates 
    the else RC [RT] = update (RC [RT], mid + . 1 , R & lt, Val); // contrary is updated to the larger side. 
    return RT; 
} 

int Query ( int U, intV, int L, int R & lt, int K) // U is the first segment, v is the second segment 
{
     int MID = (L + R & lt) >> . 1 ;
     int X = SUM [LC [U]] - SUM [LC [V]]; // SUM subtraction inside this interval represents the number of 
    IF (l == r) return L; // if l == r to reach a leaf node found described 
    IF (K <= X) return Query (LC [U], LC [V], L, MID, k); // if a large number of the k-th small interval than the left, then left section 
    return Query (RC [U], RC [V], + MID . 1 , R & lt, K - X); // if the number in the right section, should then be subtracted left section 
} //This sum is the amount actually exist, we seek to find the k-th largest in fact, what this period the number of k-interval is, if in the right range, then it should be the right section of the k-sum [] big 

int A [MAXN] , B [MAXN];
 int main () 
{ 
    int n-, m; 
    Scanf ( " % D% D " , & n-, & m);
     for ( int I = . 1 ; I <= n-; I ++) Scanf ( " % D " , & A [I]), B [I] = A [I]; 
    Sort (B + . 1 , B + . 1 + n-);
     int len = UNIQUE (B + . 1 , B + . 1 + n-) - B - . 1 ; 
    Build (the root [ 0 ],1, len);
    for (int i = 1; i <= n; i++) {
        a[i] = lower_bound(b + 1, b + 1 + len, a[i]) - b;
        root[i] = update(root[i - 1], 1, len, a[i]);
    }
    while (m--) {
        int l, r, k;
        scanf("%d%d%d", &l, &r, &k);
        int ans = query(root[r], root[l - 1], 1, len, k);
        printf("%d\n", b[ans]);
    }
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/EchoZQN/p/11329684.html