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

hdu 5919 Sequence II

时间:2018-08-31 21:56:24      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:name   close   lag   isp   color   can   turn   query   sum   

给n个数字与q次询问,每次询问找出区间不同数字的个数并输出在这个区间里第"(个数+1)/2"次出现的数字。每个数字只有第一次出现会被计数。

考虑主席树对区间不同个数的统计是基于重复的数字只保留最后出现的那次也就是说我们可以找到从后往前数字第一次出现的计数。

但现在要求的是从前向后,考虑从后向前建立主席树,那么只需要求出不同个数后再求区间第k小就搞定了。

主席树一定要开40*MAX的数组!!!!!!

 

 

 

技术分享图片
#include <bits/stdc++.h>
using namespace std;
const int M = 2e5+7;
int _,n,q,tot,tmp,pos,cas=1;
int a[M],T[M],L[40*M],R[40*M],num[40*M],flag[M];
void build(int l,int r,int &rt){
    rt=++tot;
    num[rt]=0;
    if(l==r) return ;
    int mid=(l+r)>>1;
    build(l,mid,L[rt]);
    build(mid+1,r,R[rt]);
}
void update(int l,int r,int &rt,int pre,int v){
    rt=++tot;
    num[rt]=num[pre]+v;
    if(l==r) return ;
    L[rt]=L[pre];R[rt]=R[pre];
    int mid=(l+r)>>1;
    if(pos<=mid) update(l,mid,L[rt],L[pre],v);
    else update(mid+1,r,R[rt],R[pre],v);
}
int query(int p,int l,int r,int rt){
    if(l==r){
        return num[rt];
    }
    int mid=(l+r)>>1,res=0;
    if(p<=mid){
        res+=query(p,l,mid,L[rt]);
    }
    else{
        res+=num[L[rt]];
        res+=query(p,mid+1,r,R[rt]);
    }
    return res;
}
int query1(int l,int r,int rt,int k){
    if(l==r){
        return l;
    }
    int mid=(l+r)>>1,sum=num[L[rt]];
    if(sum>=k) return query1(l,mid,L[rt],k);
    else return query1(mid+1,r,R[rt],k-sum);
}
/****************************solve********************************/
void solve(){
    int t,li,ri,cnt=0;
    build(1,n,T[cnt++]);
    for(int i=n;i>=1;i--){
        if(flag[a[i]]){
            pos=flag[a[i]];
            update(1,n,t,T[cnt-1],-1);
            pos=i;
            update(1,n,T[cnt],t,1);
        }else{
            pos=i;
            update(1,n,T[cnt],T[cnt-1],1);
        }
        flag[a[i]]=i;
        cnt++;
    }
    while(q--){
        int lii,rii,pi,ki;
        scanf("%d%d",&lii,&rii);
        li=min((lii+tmp)%n+1,(rii+tmp)%n+1);
        ri=max((lii+tmp)%n+1,(rii+tmp)%n+1);
        if(li>ri) swap(li,ri);lii=li;
        li=n-ri+1,ri=n-lii+1;
        //printf(" l:%d r:%d",li,ri);
        pi=query(n-li+1,1,n,T[ri]);
        //printf(" p:%d",pi);
        ki=(pi%2==0?pi/2:pi/2+1);
        //printf(" k:%d",ki);
        tmp=query1(1,n,T[ri],ki);
        printf(" %d",tmp);
    }
    printf("\n");
}
int main(){
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
    scanf("%d",&_);
    while(_--){
        printf("Case #%d:",cas++);
        scanf("%d%d",&n,&q);tot=0;tmp=0;
        memset(flag,0,sizeof(flag));
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        solve();
    }
    return 0;
}
View Code

 

hdu 5919 Sequence II

标签:name   close   lag   isp   color   can   turn   query   sum   

原文地址:https://www.cnblogs.com/LMissher/p/9568356.html

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