Tacca small tree-lined review - Chairman of the tree

Chairman of the tree also refers to the sustainable information that is repeated before each use of the tree line, general idea, only to open up new point as part of the update. And the so-called persistent segment tree may actually refers to persistent weights tree line, tree line is stored in each endpoint number of occurrences of this tree represents the endpoint.

The Chairman of the maintenance history for each tree among the versions are open if a new tree, then M will be the ultimate outcome. Why is the law correctly assign a number to each point of change without change directly linked to the new tree.

Here's to the Chairman of the tree from two classic issues to consider

1: The first section K minor problems  Portal

Firstly the problem, given a sequence, each time a given closed interval, minimum within this block section.

We said above, the Chairman of the tree is actually a tree line weights, which kept the point is represented by point how many times this number appears. Look at the data range, discrete not escape. Anyway, n <= 2 * 10 ^ 5

Then put into the original series discretization interval 1 --- 2 * 10 ^ 5 of. N open tree representative of the i-th particle numbers occur after each case pressed before the number i.

Declare a 3-tuple, representing the number left his son, the son of the right number, all the elements appear within the current total number of sub-tree node (if it is a leaf node represents a leaf node represents the element number of occurrences)

So the dynamic contribution not have to explain it

int Build ( int L, int R & lt) 
{ 
    int RT = ++ TOT;
     IF (L < R & lt) 
    { 
        L [RT] = Build (L, MID); // for each node in the tree structure segment left subtree position 
        R [RT] = Build (MID + . 1 , R & lt); // for each segment is configured in the right subtree of tree node position 
    }
     return RT; 
}

build (1, m) m is the number of different elements.

Here's to the inserted. Obviously, the insert must be carried out on the basis of the previous version. Then let the new versions of the left and right subtrees are equal to the old version, but the number of new versions of the root element = +1 older versions. And then determine the number of left and right under the new section inserted, as has been discretized, the new number will be inserted according to the size of the left and right divided sections. Value interval represented by the node is the leaf of x

int Update ( int the root, int L, int R & lt, int x) 
{ // discretized x is the number of inserted tape 

// front MID code has #define (L + R & lt) / 2 
    int RT = ++ TOT; 
    L [RT] = L [the root]; 
    R & lt [RT] = R & lt [the root]; 
    SUM [RT] = SUM [the root] + . 1 ;
     IF (L < R & lt) 
    { 
        IF (X <= MID) 
        { 
            L [RT ] = Update (L [the root], L, MID, X); 
            
        } 
        the else 
        { 
            R & lt [RT]=update(R[root],mid+1,r,x);
        }
    }
    return rt;
}

Here is a query, select edition L-1 and R edition, each calculated sum [L [now]] - sum [L [last]] If the result is> = k, then the value of K demonstrated a small current sub left subtree tree, or in the right sub-tree.

int query(int u,int v,int l,int r,int k)
{
    if(l==r)
    {
        return l;
    }
    int x=sum[L[v]]-sum[L[u]];
    if(x>=k)
    {
        return query(L[u],L[v],l,mid,k);
    }
    else
    {
        return query(R[u],R[v],mid+1,r,k-x);
    }
}

Then this finished, there is little need to look at discrete part.

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long int 
#define mid (l+r)/2
const int N=200001;
bool function(int a,int b)
{
    return a<b;
}
const int LOG=20;
int n,m,q,tot=0;
int a[N],b[N];
int T[N],sum[N*LOG],L[N*LOG],R[N*The LOG];
 int Build ( int L, int R & lt) 
{ 
    int RT = ++ TOT;
     IF (L < R & lt) 
    { 
        L [RT] = Build (L, MID); // for each tree node configured to have the left segment tree position 
        R & lt [RT] = Build (MID + . 1 , R & lt); // for each node in the tree structure segment position right subtree 
    }
     return RT; 
} 
int Update ( int the root, int L, int R & lt, int X) 
{ 
    int ++ = RT TOT; 
    L [RT] = L [the root]; 
    R & lt [RT]=R[root];
    sum[rt]=sum[root]+1;
    if(l<r)
    {
        if(x<=mid)
        {
            L[rt]=update(L[root],l,mid,x);
            
        }
        else
        {
            R[rt]=update(R[root],mid+1,r,x);
        }
    }
    return rt;
}
int query(int u,int v,int l,int r,int k)
{
    if(l==r)
    {
        return l;
    }
    int x=sum[L[v]]-sum[L[u]];
    if(x>=k)
    {
        return query(L[u],L[v],l,mid,k);
    }
    else
    {
        return query(R[u],R[v],mid+1,r,k-x);
    }
}
int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        b[i]=a[i];
    }
    sort(b+1,b+1+n,function);
    m=unique(b+1,b+1+n)-b-1;
    T[0]=build(1,m);
    for(int i=1;i<=n;i++)
    {
        a[i]=lower_bound(b+1,b+1+m,a[i])-b;
        T[i]=update(T[i-1],1,m,a[i]);
    }
    while(q--)
    {
            int x, y, z; 
            scanf("%d%d%d", &x, &y, &z);
            int p = query(T[x-1], T[y], 1, m, z);
            printf("%d\n", b[p]);    
    }
    return 0;
}
AC

2: looked like an ordinary tree line can be persistent segment tree

This question is no need to write the weight of the tree line, after all weights tree line to write hard.

However, this question quite honest water, really is persistable tree line directly on the bar code

#include<iostream>
#include<cstdio>
using namespace std;
struct POINT
{
    int ls,rs,maxx;
};
POINT t[100001*16];
int n,m,tot=1;
int a[10001];
int Root[100001];
void pushup(int x)
{
    t[x].maxx=max(t[t[x].ls].maxx,t[t[x].rs].maxx);
}
void build(int rt,int l,int r)
{
    if(l==r)
    {
        t[rt].maxx=a[l];
        return;
    }
    t[rt].ls=++tot;
    t[rt].rs=++tot;
    int mid=(l+r)>>1;
    build(t[rt].ls,l,mid);
    build(t[rt].rs,mid+1,r);
    pushup(rt);
}
void CHANGE(int rt1,int rt2,int l,int r,int pos,int ke)
{
    if(l==r)
    {
        t[rt1].maxx=ke;
        return ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)
    {
        t[rt1].rs=t[rt2].rs;
        t[rt1].ls=++tot;
        CHANGE(t[rt1].ls,t[rt2].ls,l,mid,pos,ke);
    }
    else
    {
        t[rt1].ls=t[rt2].ls;
        t[rt1].rs=++tot;
        CHANGE(t[rt1].rs,t[rt2].rs,mid+1,r,pos,ke);
    }
    pushup(rt1);
}
int QUERY(int rt,int l,int r,int nl,int nr)
{
    if(nl<=l&&r<=nr)
    {
        return t[rt].maxx; 
    }
    if(l==r)
    {
        return t[rt].maxx;
    }
    int sed=-998244353;
    int mid=(l+r)>>1;
    if(nl<=mid)
    {
        //cout<<t[rt].ls<<' '<<l<<' '<<mid<<endl;
        sed=max(sed,QUERY(t[rt].ls,l,mid,nl,No));
    }
    if(nr>mid)
    {
        //cout<<t[rt].rs<<' '<<mid+1<<' '<<r<<endl;
        sed=max(sed,QUERY(t[rt].rs,mid+1,r,nl,nr));
    }
    return sed;
}
void PDDFS(int x)
{
    if(x==0)
        return;
    cout<<x<<endl;
    PDDFS(t[x].ls);
    PDDFS(t[x].rs);
}
int main()
{
    freopen("longterm_segtree.in","r",stdin);
    freopen("longterm_segtree.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    build(1,1,n);
    int a1,a2,a3,a4;
    Root[1]=1;
    int cnt=1;
    while(m--)
    {
        scanf("%d%d%d%d",&a1,&a2,&a3,&a4);
        if(a1==0)
        {    //PDDFS(Root[a2]);
            cout<<QUERY(Root[a2],1,n,a3,a4)<<endl;
            
        }
        else
        {
            Root[++cnt]=++tot;
            CHANGE(Root[cnt],Root[a2],1,n,a3,a4);
        }
    }
    return 0;
}

End Sahua!

Guess you like

Origin www.cnblogs.com/XLINYIN/p/11355673.html