zoj2112--Dynamic Rankings(树状数组+主席树)

题目连接:zoj2112

给出n个点,两种操作,Q:询问在[l,r]内的第k大的数,C:更改第i个数位x

动态的询问第k大,使用树状数组修改和查询前缀和。

因为给出的空间小,所以可以将n个点做成一个静态的主席树,然后对于修改的值,在另一个主席树中修改,查询时同时查询这两个主席树就可以了。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#pragma comment(linker, "/STACK:1024000000,1024000000")
struct node{
    int l , r , num ;
}p[2500000];//所有的节点,p[i].l第i个节点的左儿子的下标,p[i].num第i个节点有的点数
int n , q , cnt ;
int a[50010] , b[10010][3] ;//a为初始的输入,b为操作数
int s[60010] , m ;//离散化的数组,和离散后的个数m
int tree[50010] , S[50010];//tree动态的主席树,使用树状数组修改/查询前缀和,S静态的主席树,保留初始的n个点的前缀和。
int use[50010] ;
int lowbit(int x) {
    return x & -x ;
}
int build(int l,int r) {
    int x = cnt++ , mid = (l+r)/2 ;
    p[x].num = 0 ;
    if( l < r ) {
        p[x].l = build(l,mid) ;
        p[x].r = build(mid+1,r) ;
    }
    return x ;
}
int search1(int x) {
    int low = 0 , mid , high = m-1 ;
    while( low <= high ) {
        mid = (low + high)/2 ;
        if( s[mid] == x ) return mid ;
        else if( s[mid] < x ) low = mid + 1 ;
        else high = mid - 1 ;
    }
}
int update(int y,int k,int num) {
    int root = cnt++ , x = root ;
    int l = 0 , r = m-1 , mid ;
    p[x].num = p[y].num + num ;
    while( l < r ) {
        mid = (l+r)/2 ;
        if( k <= mid ) {
            r = mid ;
            p[x].l = cnt++ ;
            p[x].r = p[y].r ;
            x = p[x].l ;
            y = p[y].l ;
        }
        else {
            l = mid + 1 ;
            p[x].l = p[y].l ;
            p[x].r = cnt++ ;
            x = p[x].r ;
            y = p[y].r ;
        }
        p[x].num = p[y].num + num ;
    }
    return root ;
}
void init() {
    int k , i , j ;
    sort(s,s+m) ;
    m = unique(s,s+m)-s ;
    cnt = 0 ;
    S[0] = build(0,m-1) ;
    for(i = 1 ; i <= n ; i++)
        S[i] = update(S[i-1],search1(a[i]),1) ;
    for(i = 1 ; i <= n ; i++)
        tree[i] = S[0] ;
}
int sum(int i) {
    int sum = 0 ;
    while( i ) {
        sum += p[ p[ use[i] ].l ].num ;
        i -= lowbit(i) ;
    }
    return sum ;
}
void query(int ll,int rr,int k) {
    int num , i , l = 0 , r = m-1 , mid , rt_l = S[ll-1] , rt_r = S[rr] ;
    for(i = ll-1 ; i ; i -= lowbit(i)) use[i] = tree[i] ;
    for(i = rr ; i ; i -= lowbit(i)) use[i] = tree[i] ;
    while( l < r ) {
        num = sum(rr) - sum(ll-1) + p[ p[rt_r].l ].num - p[ p[rt_l].l ].num ;
        mid = (l + r ) / 2 ;
        if( num >= k ) {
            r = mid ;
            for(i = ll-1 ; i ; i -= lowbit(i))
                use[i] = p[ use[i] ].l ;
            for(i = rr ; i ; i -= lowbit(i))
                use[i] = p[ use[i] ].l ;
            rt_l = p[ rt_l ].l ;
            rt_r = p[ rt_r ].l ;
        }
        else {
            l = mid + 1 ;
            k -= num ;
            for(i = ll-1 ; i ; i -= lowbit(i))
                use[i] = p[ use[i] ].r ;
            for(i = rr ; i ; i -= lowbit(i))
                use[i] = p[ use[i] ].r ;
            rt_l = p[ rt_l ].r ;
            rt_r = p[ rt_r ].r ;
        }
    }
    printf("%d\n", s[l]) ;
}
int main() {
    int t , i , j , k1 , k2 ;
    int l , r ;
    char str[10] ;
    scanf("%d", &t) ;
    while( t-- ) {
        scanf("%d %d", &n, &q) ;
        m = 0 ;
        for(i = 1 ; i <= n ; i++) {
            scanf("%d", &a[i]) ;
            s[m++] = a[i] ;
        }
        for(i = 0 ; i < q ; i++) {
            scanf("%s", str) ;
            if( str[0] == 'Q' ) {
                scanf("%d %d %d", &b[i][0], &b[i][1], &b[i][2]) ;
            }
            else {
                b[i][0] = -1 ;
                scanf("%d %d", &b[i][1], &b[i][2]) ;
                s[m++] = b[i][2] ;
            }
        }
        init() ;
        for(i = 0 ; i < q ; i++) {
            if( b[i][0] == -1 ) {
                k1 = search1( a[ b[i][1] ] ) ;
                k2 = search1( b[i][2] ) ;
                for(j = b[i][1] ; j <= n ; j += lowbit(j)) {
                    tree[j] = update(tree[j],k1,-1) ;
                    tree[j] = update(tree[j],k2,1) ;
                }
                a[ b[i][1] ] = b[i][2] ;
            }
            else {
                query(b[i][0],b[i][1],b[i][2]) ;
            }
        }
    }
    return 0 ;
}


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。