hdu5919 Sequence II(主席树)

来源:互联网 发布:淘宝如何申请售后 编辑:程序博客网 时间:2024/05/14 18:35

题目链接:

hdu5919

题意:

给你n(n2105)个数,每个数的大小0<Ai2105。再给你m(m2105)个询问。对于每个询问输入l,r,表示Al...Ar这个区间我们得到每个数第一次出现的位置下标的排列,假设这个区间有k个不同的数,我们得到的排列是p1<p2<p3<...<pk,叫你求第(k+1)/2这个数是多少?

题解:

1、我们利用主席树记录相同的数的前一个位置是多少,很容易得到区间有多少个不同的数,但是我们要得到第(k+1)/2这个数的话我们要二分去求解。时间复杂度为O(nlog2(n)),,在hdu会超时。

2、如果我们从后往前的话在当前位置i我们在主席树上i这个位置加1,在它之前出现的位置减1,然后我们在主席树询问区间的时候每个数都只出现一次了,就不用二分去找那个位置了,时间复杂度退化成O(nlog(n))

代码:

#include<cstdio>#include<cstring>#include<iostream>#include<sstream>#include<algorithm>#include<vector>#include<bitset>#include<set>#include<queue>#include<stack>#include<map>#include<cstdlib>#include<cmath>#define PI 2*asin(1.0)#define LL long long#define pb push_back#define pa pair<int,int>#define clr(a,b) memset(a,b,sizeof(a))#define lson lr<<1,l,mid#define rson lr<<1|1,mid+1,r#define bug(x) printf("%d++++++++++++++++++++%d\n",x,x)#define key_value ch[ch[root][1]][0]const int  MOD = 1000000007;const int N = 2e5 + 15;const int maxn = 100+ 14;const int letter = 130;const int INF = 1e9;const double pi=acos(-1.0);const double eps=1e-8;using namespace std;inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}int n,q,pre[N],a[N],sum[N*36],ls[N*36],rs[N*36],root[N];int siz,ps[N];void insert(int x,int &y,int l,int r,int d,int v){    y=++siz;    ls[y]=ls[x],rs[y]=rs[x],sum[y]=sum[x]+v;    if(l==r) return;    int mid=(l+r)>>1;    if(d<=mid) insert(ls[x],ls[y],l,mid,d,v);    else insert(rs[x],rs[y],mid+1,r,d,v);}int query(int x,int l,int r,int ll,int rr){    if(ll<=l&&r<=rr) return sum[x];    int mid=(l+r)>>1;    int ans=0;    if(ll<=mid) ans+=query(ls[x],l,mid,ll,rr);    if(rr>mid)  ans+=query(rs[x],mid+1,r,ll,rr);    return ans;}int find_k(int x,int l,int r,int k){    if(l==r) return l;    int mid=(l+r)>>1;    if(sum[ls[x]]>=k) return find_k(ls[x],l,mid,k);    else return find_k(rs[x],mid+1,r,k-sum[ls[x]]);}int main(){    int T,cas=0;    scanf("%d",&T);    while(T--){        scanf("%d%d",&n,&q);        clr(pre,0),siz=0;        clr(root,0);        for(int i=1;i<=n;i++) scanf("%d",a+i);        for(int i=n;i;i--){            insert(root[i+1],root[i],1,n,i,1);            if(pre[a[i]]) insert(root[i],root[i],1,n,pre[a[i]],-1);            pre[a[i]]=i;        }        ps[0]=0;        for(int i=1;i<=q;i++){            int l,r;            scanf("%d%d",&l,&r);            l=(l+ps[i-1])%n+1,r=(r+ps[i-1])%n+1;            if(l>r) swap(l,r);            int mid=query(root[l],1,n,l,r);            mid=(mid+1)/2;            ps[i]=find_k(root[l],1,n,mid);        }        printf("Case #%d:",++cas);        for(int i=1;i<=q;i++) printf(" %d",ps[i]);        puts("");    }    return 0;}
0 0
原创粉丝点击