HDU - 5919主席树区间不同数+区间第K大

Posted lmcc1108

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 5919主席树区间不同数+区间第K大相关的知识,希望对你有一定的参考价值。

 HDU - 5919 

题意:n个数,m个询问,每次询问区间[l,r],设[l,r]内不同的数有k个,它们在该区间第一个次出现的位置是p1,p2...pk(p1<p2<pk),回答p(k+1)/2.

思路:主席树查区间不同的数的个数这个就不说了,前面的博客有提到过。问题就在于我们在知道k之后,找p(k+1)/2,难道需要在重新建一棵以权值线段树建的主席树,或者二分去找?

其实并不用,在前面博客查区间不同的数的时候我们是从左往右建的,这样的话,主席树中,相同的数都是保存在当前出现过的最右位置。那反过来,从右往左建的话,相同的数就是保存在当前出现过的最左位置,然后再在这方面找第(k+1)/2大的数即可。

技术图片
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+11;
struct Tree{
    int lson,rson,val;
}T[N*32];
int tn,a[N],root[N],vis[N];
int build(int l,int r){
    int cur=++tn,mid=(l+r)>>1;
    T[cur].val=0;
    T[cur].lson=T[cur].rson=0;
    if(l==r) return cur;
    T[cur].lson=build(l,mid);
    T[cur].rson=build(mid+1,r);
    return cur;
}
int addT(int x,int l,int r,int p,int val){
    int cur=++tn,mid=(l+r)>>1;
    T[cur]=T[x];
    T[cur].val=T[x].val+val;
    if(l==r) return cur;
    if(p<=mid) T[cur].lson=addT(T[x].lson,l,mid,p,val);
    else T[cur].rson=addT(T[x].rson,mid+1,r,p,val);
    return cur;
}
int query(int x,int l,int r,int qr){
    if(r<=qr) return T[x].val;
    int ans=0,mid=(l+r)>>1;
    ans+=query(T[x].lson,l,mid,qr);
    if(qr>mid) ans+=query(T[x].rson,mid+1,r,qr);
    return ans;
}
int findk(int x,int l,int r,int k){
    if(l==r) return l;
    int mid=(l+r)>>1;
    int lval=T[T[x].lson].val;
    if(lval>=k) return findk(T[x].lson,l,mid,k);
    else return findk(T[x].rson,mid+1,r,k-lval); 
} 
int main(){
    int t=1,T;
    scanf("%d",&T);
    while(T--){
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            vis[a[i]]=0;
        }
        tn=0;
        root[n+1]=build(1,n);
        for(int i=n;i>=0;i--){
            int tempr=root[i+1];
            if(vis[a[i]]) tempr=addT(tempr,1,n,vis[a[i]],-1);
            root[i]=addT(tempr,1,n,i,1);
            vis[a[i]]=i;
        }
        int l,r,ans=0;
        printf("Case #%d:",t++);
        while(m--){
            scanf("%d%d",&l,&r);
            l=(l+ans)%n+1;r=(r+ans)%n+1;
            if(l>r) swap(l,r);
            int pos=query(root[l],1,n,r);
            pos=(pos+1)/2;
            ans=findk(root[l],1,n,pos);
            printf(" %d",ans);
        }
        printf("
");
    }
    return 0;
}
主席树下主席果

 

以上是关于HDU - 5919主席树区间不同数+区间第K大的主要内容,如果未能解决你的问题,请参考以下文章

hdu 5919 主席树(区间不同数的个数 + 区间第k大)

hdu 5919--Sequence II(主席树--求区间不同数个数+区间第k大)

HDU 5919 - Sequence II (2016CCPC长春) 主席树 (区间第K小+区间不同值个数)

HDU 5919 Sequence II ( 主席树 )

HDU 5919 Sequence II(主席树)题解

hdu 5919 Sequence II