1. 程式人生 > >hdu 5919 Sequence II

hdu 5919 Sequence II

set opened bsp ase aps stdin 個數 ++ 建立

給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