Unmodified Chairman (HJT) tree - HDU2665, POJ-2104;

Reference: Excellent B station video;

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

I feel that the idea of ​​​​the chairman tree is really excellent. Each time a new small line segment tree is built on the basis of the previous line segment tree; therefore, updates and queries require two root nodes before and after the operation;

Using the reference, only modify the node this time without moving the previous line segment tree;

The chairman tree can be used to find the Kth largest number in the interval : the idea is:

We can also use the idea of ​​prefix sum to solve the problem of tree building. We only need to build n "prefix" line segment trees. The i-th tree maintains the [1, i] sequence, so that when we process any interval l, r, we can pass Just process the interval [1,l - 1], [1,r], and then add and subtract the processing results of the two. Why it satisfies the properties of addition and subtraction, we can easily get it by simple analysis. If there are x numbers less than one number in the interval [1,l - 1] and y numbers less than that number in [1,r], then there are y - x numbers in the interval [l,r] It is less than that number, so it is easy to understand why it can be added and subtracted. In addition, the structure of each tree is the same, and it is a line segment tree with n leaf nodes.

There is also an operation that uses vector discretization;

hdu ac 的 :

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
using namespace std;
#define pb push_back 
const int maxn = 100009;

struct node {
    int l,r;
    int sum;
}T[maxn*20];
int a[maxn],root[maxn];
vector<int>v;
int getid(int x){
    return lower_bound(v.begin(),v.end(),x) - v.begin() + 1;
}
int n,m,cnt,x,y,k;
    
void init(){
    v.clear();
    memset(T,0,sizeof(T));
    cnt = 0;
}
void update(int l,int r,int &x,int y,int pos)
{
    T[++cnt] = T[y]; T[cnt].sum++; x = cnt;
    if(l==r)return;
    int mid = (l+r)>>1;
    if(mid>=pos)
        update(l,mid,T[x].l,T[y].l,pos);
    else update(mid+1,r,T[x].r,T[y].r,pos);
}
        
int query ( int l, int r, int x, int y, int pos)
{
    if(l==r)return l;
    int sum = T[T[y].l].sum - T[T[x].l].sum;
    int mid = (l+r)>>1;
    if(sum >= pos)
        return query(l,mid,T[x].l,T[y].l,pos);
    else return query(mid+1,r,T[x].r,T[y].r,pos - sum); 
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++)
        {
            scanf("%d", &a[i]);
            v.pb(a[i]);
        }
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(),v.end()),v.end());

        for(int i=1; i<=n; i++)
            update(1,n,root[i],root[i-1],getid(a[i]));
        for(int i=1; i<=m; i++)
        {
            int le, ri, k;
            scanf("%d%d%d", &le,&ri,&k);
            printf("%d\n",v[query(1,n,root[le-1],root[ri],k)-1]);
        }
    }
    return 0;
}

POJ 的

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
using namespace std;
#define pb push_back 
const int maxn = 100009;

struct node {
    int l,r;
    int sum;
}T[maxn*40];
int a[maxn],root[maxn];
vector<int>v;
int getid(int x){
    return lower_bound(v.begin(),v.end(),x) - v.begin() + 1;
}
int n,m,cnt,x,y,k;
    
void update(int l,int r,int &x,int y,int pos)
{
    T[++cnt] = T[y]; T[cnt].sum++; x = cnt;
    if(l==r)return;
    int mid = (l+r)>>1;
    if(mid>=pos)
        update(l,mid,T[x].l,T[y].l,pos);
    else update(mid+1,r,T[x].r,T[y].r,pos);
}
        
int query ( int l, int r, int x, int y, int pos)
{
    if(l==r)return l;
    int sum = T[T[y].l].sum - T[T[x].l].sum;
    int mid = (l+r)>>1;
    if(sum >= pos)
        return query(l,mid,T[x].l,T[y].l,pos);
    else return query(mid+1,r,T[x].r,T[y].r,pos - sum); 
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)
    {
        scanf("%d", &a[i]);
        v.pb(a[i]);
    }
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(),v.end()),v.end());

    for(int i=1; i<=n; i++)
        update(1,n,root[i],root[i-1],getid(a[i]));
    for(int i=1; i<=m; i++)
    {
        int le, ri, k;
        scanf("%d%d%d", &le,&ri,&k);
        printf("%d\n",v[query(1,n,root[le-1],root[ri],k)-1]);
    }

    return 0;
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325274867&siteId=291194637