HDU--5519 Sequence II (主席树)

题目链接 2016年长春ccpc I 题

题目大意 :

给你n(n≤2∗105n≤2∗105)个数,每个数的大小 0<Ai≤2∗10^5   0<Ai≤2∗10^5。

再给你m(m≤2∗105≤2∗105)个询问。对于每个询问输入l,r,表示Al...ArAl...Ar这个区间我们得到每个数第一次出现的位置下标的排列,

假设这个区间有k个不同的数,我们得到的排列是p1<p2<p3<...<pkp1<p2<p3<...<pk,叫你求第(k+1)/2这个数是所在的位置是哪个?

主席树正着插能得到每个区间不同数最后一次出现的位置,反着插的话可以得到每个不同数第一次出现的位置

然后就是查找区间k值

#include<bits/stdc++.h>
using namespace std;
#define maxn 200005
struct ac{
  int va,l,r;
}tre[40*maxn];
int a[maxn],root[maxn],tot,fa[maxn];
void init(){
   memset(root,0,sizeof(root));
   memset(tre,0,sizeof(tre));
   memset(fa,0,sizeof(fa));
   tot=0;
}
void updata(int l,int r,int &x,int y,int z,int va){
   tre[++tot]=tre[y];
   tre[tot].va+=va;
   x=tot;
   if(l==r) return ;
   int mid=(l+r)/2;
   if(z<=mid) updata(l,mid,tre[x].l,tre[y].l,z,va);
   else updata(mid+1,r,tre[x].r,tre[y].r,z,va);
}
int query(int l,int r,int x,int k){
   if(l==r) return l;
   int s=tre[tre[x].l].va;
   int mid=(l+r)/2;
   if(k<=s){
      return query(l,mid,tre[x].l,k);
   }
   return query(mid+1,r,tre[x].r,k-s);
}
int getsum(int l,int r,int x,int y,int z){
   if(l==x&&y==r) return tre[z].va;
   int mid=(l+r)/2;
   if(y<=mid){
      return getsum(l,mid,x,y,tre[z].l);
   }else if(x>mid){
      return getsum(mid+1,r,x,y,tre[z].r);
   }else{
      return getsum(l,mid,x,mid,tre[z].l)+getsum(mid+1,r,mid+1,y,tre[z].r);
   }
}
int main(){
   int t,cnt=1;
   cin>>t;
   while(t--){
      init();
      int n,m;
      cin>>n>>m;
      for(int j=1;j<=n;j++){
         scanf("%d",&a[j]);
      }
      for(int j=n;j>=1;j--){
         if(fa[a[j]]){
            updata(1,n,root[j],root[j+1],fa[a[j]],-1);
            updata(1,n,root[j],root[j],j,1);
         }else{
            updata(1,n,root[j],root[j+1],j,1);
         }
         fa[a[j]]=j;
      }
      int ans=0;
      printf("Case #%d:",cnt++);
      for(int j=0;j<m;j++){
         int x,y,l,r;
         scanf("%d%d",&x,&y);
         x=(x+ans)%n+1;
         y=(y+ans)%n+1;
         l=min(x,y);r=max(x,y);
         int s=getsum(1,n,l,r,root[l]);
         s=(s+1)/2;
         ans=query(1,n,root[l],s);
         printf(" %d",ans);
      }
      printf("
");
   }
}
原文地址:https://www.cnblogs.com/Dvelpro/p/9775034.html