码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2020-07-09 00:40:09      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:const   col   区间   ref   alt   bit   spl   保存   struct   

 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("\n");
    }
    return 0;
}
主席树下主席果

 

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

标签:const   col   区间   ref   alt   bit   spl   保存   struct   

原文地址:https://www.cnblogs.com/LMCC1108/p/13270156.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!