主席树

一、区间第k小
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

const int N = 200005;

int n, m, b[N], qwq[N];

struct node {
    node *ls, *rs;
    int num;
} pool[N*32], *zero, *tail = pool, *root[N];

struct edge {
    int id, lar;
} a[200005];

void update ( node *nd ) {
    nd -> num = nd -> ls -> num + nd -> rs -> num;
}

node *build ( ) {
    zero = ++tail;
    zero -> ls = zero;
    zero -> rs = zero;
    zero -> num = 0;
    node *nd = ++ tail;
    nd -> ls = zero;
    nd -> rs = zero;
    nd -> num = 0;
    return nd;
}

node *newnode ( ) {
    node *nd = ++tail;
    nd -> ls = zero;
    nd -> rs = zero;
    nd -> num = 0;
    return nd;
}

node *insert ( node *nd, int l, int r, int pos, int delta ) {
    node *nnd = newnode ( );
    if ( l == r ) {
        nnd -> num = nd -> num + delta;
        return nnd;
    }
    int mid = ( l + r ) >> 1;
    if ( mid >= pos ) { ////区间严格对应
        nnd -> rs = nd -> rs;
        nnd -> ls = insert ( nd -> ls, l, mid, pos, delta );
    }
    if ( mid < pos ) { ////
        nnd -> ls = nd -> ls;
        nnd -> rs = insert ( nd -> rs, mid + 1, r, pos, delta );
    }
    update ( nnd ); ////
    return nnd;
}

int query ( node *ld, node *rd, int l, int r, int k ) {
    if ( l == r ) return l;
    int mid = ( l + r ) >> 1;
    int ans;
    int lz = rd -> ls -> num - ld -> ls -> num;
    if ( lz < k ) ans = query ( ld -> rs, rd -> rs, mid + 1, r, k - lz );
    else ans = query ( ld -> ls, rd -> ls, l, mid, k );
    return ans;
}

bool cmp ( edge a, edge b ) {
    return a.lar < b.lar;
}

int aa[N];
int main ( ) {
    scanf ( "%d%d", &n, &m );
    root[0] = build ( );
    for ( int i = 1; i <= n; i ++ ) {
        scanf ( "%d", &aa[i] );
        a[i].id = i; a[i].lar = aa[i];
    }
    sort ( a + 1, a + 1 + n, cmp );
    for ( int i = 1; i <= n; i ++ ) {
        b[a[i].id] = i;
    }
    for ( int i = 1; i <= n; i ++ )
        qwq[i] = a[i].lar; ////离散化
    for ( int i = 1; i <= n; i ++ )
        root[i] = insert ( root[i-1], 1, n, b[i], 1 );
    for ( int i = 1; i <= m; i ++ ) {
        int l, r, k;
        scanf ( "%d%d%d", &l, &r, &k );
        int ans = query ( root[l-1], root[r], 1, n, k );
        printf ( "%d\n", qwq[ans] );
    }
    return 0;
}
二、动态区间第k小
//数组版本
//https://blog.csdn.net/qq_24855707/article/details/78069710
#prag\
ma GCC optimize("O3") 
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#define mid (l+r>>1)
#define mid_1 ((l+r>>1)+1)
#define R(XXX) scanf("%d",&XXX)
#define DR(XXX,YYY) scanf("%d%d",&XXX,&YYY)
#define TR(XXX,YYY,ZZZ) scanf("%d%d%d",&XXX,&YYY,&ZZZ)
#define P(XXX) printf("%d\n",XXX)
#define lowbit(i) (i&-i)
using namespace std;
const int N = 50005;

int a[N], n, m, tot, Max, _0, _1, _2;

char cmd;
int ver[N], c[26000010], v, d;
int xx[N], yy[N], ls[26000010], rs[26000010];


void update( int &p, int l, int r ){
    if( ! p ) p = ++ tot; c[p] += d;
    if( l == r ) return;
    if( v <= mid ) update( ls[p], l, mid );
    else update( rs[p], mid_1, r );
}

void modify(){
    DR( _0, _1 );
    d = -1; v = a[_0];
    for( int i = _0; i <= n; i += lowbit(i) )
        update( ver[i], 0, N );
    d = 1; v = _1;
    for( int i = _0; i <= n; i += lowbit(i) )
        update( ver[i], 0, N );
    a[_0] = _1;
}


int query(){
    TR( _0, _1, _2 ); _0 --;
    int x = 0, y = 0, tmp;
    for( int i = _1; i; i ^= lowbit( i ) ) xx[x++] = ver[i];
    for( int i = _0; i; i ^= lowbit( i ) ) yy[y++] = ver[i];
    int l = 0, r = N;
    while( l < r ){
        tmp = 0;
        for( int i = 0; i < x; i ++ ) tmp += c[ls[xx[i]]];
        for( int i = 0; i < y; i ++ ) tmp -= c[ls[yy[i]]];
        if( _2 <= tmp ){
            for( int i = 0; i < x; i ++ ) xx[i] = ls[xx[i]];
            for( int i = 0; i < y; i ++ ) yy[i] = ls[yy[i]];
            r = mid;
        }
        else{
            for( int i = 0; i < x; i ++ ) xx[i] = rs[xx[i]];
            for( int i = 0; i < y; i ++ ) yy[i] = rs[yy[i]];
            _2 -= tmp; l = mid_1;
        }
    }
    return l;
}


int main()
{
//  freopen("tt.in","r",stdin);
    DR( n, m );
    d = 1;
    for( int i = 1; i <= n; i ++ ){ R(a[i]); v = a[i];
        for( int j = i; j <= n; j += lowbit(j) )
            update( ver[j], 0, N ); }
    while( m -- ){
        cin >> cmd;
        if( cmd == 'C' ) modify();
        else P( query() );
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值