Luo Gu P3834 solution to a problem

If you want in-depth study of Chairman trees portal .


Description:

A given number of columns \ (\ {A_N \} \) , seeking the closed interval \ ([l, r] \ ) of \ (K \) small numbers.

Method:

Discrete data first, and then build tree line in accordance with the weights.

To find \ ([1, p] \ ) of \ (k \) is small, start from the root process. Defined \ (Son_ {left} \) represents the set of the left son, \ (right Son_ {} \) represents the set of the right son. If \ (| Son_ {left} | \ ge k \) , the description of the \ (k \) small numbers in the left subtree, left his son to root for the new updated recursively down, looking left subtree first (k \) \ small numbers; on the contrary, a description \ (k \) small numbers in the right subtree, left his son to root for the new updated recursively down, looking left subtree of \ (k- | Son_ {left} | \) small numbers.

Expand a bit, let's achievements pretreatment obtain \ (n + 1 \) version of the tree line (including the initial segment tree), numbered \ (0 \ the SIM the n-\) .

Mentioned before, the President of trees to meet the prefix thought and inquiry, so we ask \ ([l, r] \ ) of \ (k \) small value, you can use sum[r]-sum[l-1].

Code:

#include<bits/stdc++.h>
#define int long long 
#define Maxn 200010
using namespace std;
inline void read(int &x)
{
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}
int n,m;
struct Segtree
{
    int ls,rs,sum;
}tree[Maxn<<5];
int rt[Maxn];
int a[Maxn],ins[Maxn]; 
int len,tot=0;
inline void Init(){tot=0;}
inline int getid(const int &x)
{
    return lower_bound(ins+1,ins+len+1,x)-ins;
}
inline void pushup(int rt)
{
    tree[rt].sum=tree[tree[rt].ls].sum+tree[tree[rt].rs].sum;
}
inline int build(int l,int r)
{
    int rt=++tot;
    if(l==r) 
    {
        tree[rt].sum=0;
        return rt;
    }
    int mid=(l+r)/2;
    tree[rt].ls=build(l,mid);
    tree[rt].rs=build(mid+1,r);
    pushup(rt);
    return rt;
}
int update(int k,int l,int r,int root,int val)
{
    int rt=++tot;
    tree[rt]=tree[root];
    if(l==k&&r==k)
    {
        tree[rt].sum+=val;
        return rt;
    }
    int mid=(l+r)/2;
    if(k<=mid) tree[rt].ls=update(k,l,mid,tree[rt].ls,val);
    else tree[rt].rs=update(k,mid+1,r,tree[rt].rs,val);
    pushup(rt);
    return rt;
}
int query(int u,int v,int l,int r,int k)
{
    if(l==r) return l;
    int mid=(l+r)/2,x=tree[tree[v].ls].sum-tree[tree[u].ls].sum;
    if(k<=x) return query(tree[u].ls,tree[v].ls,l,mid,k);
    else return query(tree[u].rs,tree[v].rs,mid+1,r,k-x);
}
signed main()
{
    Init();
    read(n),read(m);
    for(int i=1;i<=n;i++)
    {
        read(a[i]);
    }
    memcpy(ins,a,sizeof(ins));
    sort(ins+1,ins+n+1);
    len=unique(ins+1,ins+n+1)-ins-1;
    rt[0]=build(1,len);
    for(int i=1;i<=n;i++)
    {
        rt[i]=update(getid(a[i]),1,len,rt[i-1],1);
    }
    while(m--)
    {
        int l,r,k;
        read(l),read(r),read(k);
        printf("%lld\n",ins[query(rt[l-1],rt[r],1,len,k)]);
    }
    return 0;
}

Warning:

  • ls[], rs[], sum[]And other array to be multiplied by \ (2 ^ 5 \) .
  • Discrete take lower_boundtime, minus any leading 0 is the last address, not the address beginning with 1. (That is lower_bound(ins+1,ins+n+1,x)-ins, not lower_bound(ins+1,ins+n+1,x)-ins-1)
  • Find a recursive query right subtree of \ (k- | Son_ {left} | \) small, instead of \ (k \) small.

Guess you like

Origin www.cnblogs.com/nth-element/p/11785026.html