hdu 5919 Sequence II
Posted lmissher
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 5919 Sequence II相关的知识,希望对你有一定的参考价值。
给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(" "); } 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; }
以上是关于hdu 5919 Sequence II的主要内容,如果未能解决你的问题,请参考以下文章