动态区间第k小主席树模板

const int maxn = 60010;
const int maxm = maxn*40;
int n,q,m,tot;
int a[maxn],b[maxn];
int T[maxn],lson[maxm],rson[maxm],c[maxm];
int S[maxn],use[maxn];
int Build( int l , int r )
{
    int root = tot++;
    c[root] = 0;
    if ( l!=r )
    {
        int mid = ( l+r )>>1;
        lson[root] = Build( l , mid );
        rson[root] = Build( mid+1 , r );
    }
    return root;
}
int Update( int root , int pos , int val )
{
    int newroot = tot++,tmp = newroot;
    int l = 0,r = m-1;
    c[newroot] = c[root]+val;
    while ( l<r )
    {
        int mid = (l+r)>>1;
        if ( pos<=mid )
        {
            lson[newroot] = tot++; rson[newroot] = rson[root];
            newroot = lson[newroot]; root = lson[root]; r = mid;
        }
        else
        {
            rson[newroot] = tot++; lson[newroot] = lson[root];
            newroot = rson[newroot]; root = rson[root]; l = mid+1;
        }
        c[newroot] = c[root]+val;
    }
    return tmp;
}
int lowbit( int x )
{
    return x&(-x);
}
void add( int x , int pos , int val )
{
    for ( ; x<=n ; x+=lowbit(x) )
        S[x] = Update( S[x] , pos , val );
}
int sum( int x )
{
    int res = 0;
    for ( ; x>=1 ; x-=lowbit(x) )
        res += c[lson[use[x]]];
    return res;
}
int Query( int left , int right , int k )
{
    int left_root = T[left-1];
    int right_root = T[right];
    int l = 0,r = m-1;
    for ( int i=left-1 ; i>=1 ; i-=lowbit(i) ) use[i] = S[i];
    for ( int i=right  ; i>=1 ; i-=lowbit(i) ) use[i] = S[i];
    while ( l<r )
    {
        int mid = (l+r)>>1;
        int tmp = sum(right)-sum(left-1)+c[lson[right_root]]-c[lson[left_root]];
        if ( k<=tmp )
        {
            r = mid;
            for ( int i=left-1 ; i>=1 ; i-=lowbit(i) ) use[i] = lson[use[i]];
            for ( int i=right  ; i>=1 ; i-=lowbit(i) ) use[i] = lson[use[i]];
            left_root = lson[left_root];
            right_root = lson[right_root];
        }
        else
        {
            l = mid+1;
            k -= tmp;
            for ( int i=left-1 ; i>=1 ; i-=lowbit(i) ) use[i] = rson[use[i]];
            for ( int i=right  ; i>=1 ; i-=lowbit(i) ) use[i] = rson[use[i]];
            left_root = rson[left_root];
            right_root = rson[right_root];
        }
    }
    return l;
}
void Modify( int x , int p , int d )
{
    for ( ; x<=n ; x+=lowbit(x) )
        S[x] = Update( S[x] , p , d );
}
struct node
{
    char op[5];
    int l,r,k;
}data[10010];
int main()
{
    for ( int t ; scanf ( "%d" , &t )==1 ; )
    {
        for ( int cas=1 ; cas<=t ; cas++ )
        {
            scanf ( "%d%d" , &n , &q );
            tot = 0,m = 0;
            for ( int i=1 ; i<=n ; i++ )
                scanf ( "%d" , &a[i] ),b[m++] = a[i];
            for ( int i=1 ; i<=q ; i++ )
            {
                scanf ( "%s" , data[i].op );
                if ( data[i].op[0]=='Q' )
                    scanf ( "%d%d%d" , &data[i].l , &data[i].r , &data[i].k );
                else
                    scanf ( "%d%d" , &data[i].l , &data[i].r ),b[m++] = data[i].r;
            }
            sort ( b , b+m );
            m = unique( b , b+m )-b;
            T[0] = Build( 0 , m-1 );
            for ( int i=1 ; i<=n ; i++ )
            {
                int pos = lower_bound( b , b+m , a[i] )-b;
                T[i] = Update( T[i-1] , pos , 1 );
            }
            for ( int i=1 ; i<=n ; i++ )
                S[i] = T[0];
            for ( int i=1 ; i<=q ; i++ )
            {
                if ( data[i].op[0]=='Q' )
                    printf( "%d\n" , b[Query( data[i].l , data[i].r , data[i].k )] );
                else
                {
                    int pos = lower_bound( b , b+m , a[data[i].l] )-b;
                    Modify( data[i].l , pos , -1 );
                    pos = lower_bound( b , b+m , data[i].r )-b;
                    Modify( data[i].l , pos , 1 );
                    a[data[i].l] = data[i].r;
                }
            }
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值