1. 程式人生 > >hdu 5919(主席樹)

hdu 5919(主席樹)

思路:主席樹的模板題目,我們倒著插入題目就變成了,查詢區間不同數的個數k,然後查詢區間第(k+1)/2大。寫了一下午,發現初始化寫錯了,初始化的cnt應該是1,還有陣列大小要開36倍左右,我剛開始開的20倍一直tle。

#include <stdio.h>
#include <string.h>
#include <algorithm>;
const int N = 2e5 + 15;
using namespace std;
struct TR{
	int l,r,sum;
}tree[N*36];
int rot[N];
int cnt;
//普通讀入優化
void read(int &x)
{
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}

void build(int l,int r,int &rt,int pos,int val)
{
	tree[cnt++]=tree[rt];
	rt=cnt-1;
	tree[rt].sum+=val;
	int mid=(l+r)>>1;
	if(l==r) return ;
	if(pos<=mid) build(l,mid,tree[rt].l,pos,val);
	else build(mid+1,r,tree[rt].r,pos,val);
	return ;
}
int query(int L,int R,int rt,int l,int r)
{
	if(L<=l&&R>=r) return tree[rt].sum;
	int mid=(l+r)>>1;
	int ans=0;
	if(L<=mid) ans+=query(L,R,tree[rt].l,l,mid);
	if(R>mid) ans+=query(L,R,tree[rt].r,mid+1,r);
	return ans;
}
int query1(int rt,int l,int r,int k)
{
	if(l==r) return l;
	int mid=(l+r)>>1;
	int ans=tree[tree[rt].l].sum;
	if(ans>=k) return query1(tree[rt].l,l,mid,k);
	else return query1(tree[rt].r,mid+1,r,k-ans);
}
int a[N];
int ans[N];int pre[N];
void init(int rt)
{
	cnt=1;
	ans[0]=0;memset(rot,0,sizeof(rot));
	tree[rt].l=tree[rt].r=tree[rt].sum=0;memset(pre,0,sizeof(pre));
}
int main()
{
	int t;read(t);int cas=1;
	while(t--)
	{
		int n,q;
		scanf("%d%d",&n,&q);
		for(int i=1;i<=n;i++) read(a[i]);
		init(n+1);
		for(int i=n;i>=1;i--)
		{
			if(pre[a[i]])
			{
				rot[i]=rot[i+1];
				build(1,n,rot[i],pre[a[i]],-1);
				build(1,n,rot[i],i,1);
			}
			else
			{
				rot[i]=rot[i+1];
				build(1,n,rot[i],i,1);
			}
			pre[a[i]]=i;
		}
		for(int i=1;i<=q;i++)
		{
			int l,r;read(l);read(r);
			l=(l+ans[i-1])%n+1;
			r=(r+ans[i-1])%n+1;
			if(l>r) swap(l,r);
			int k=query(l,r,rot[l],1,n); 
			k=(k+1)/2;
			ans[i]=query1(rot[l],1,n,k);//直接查第l顆樹的第(k+1)/2大即可。因為區間[r+1,n]的數肯定都大於等於[l,r]區間的數。 
		}
		printf("Case #%d: ",cas++);
		for(int i=1;i<=q;i++)
		{
			if(i!=q)
			printf("%d ",ans[i]);
			else printf("%d\n",ans[i]);
		}
	}
	return 0;
}