主席树(hdu2665)

版权声明:转载什么的无所谓啦,反正注明一下出处就行啦~ https://blog.csdn.net/u013672056/article/details/76220036
Give you a sequence and ask you the kth big number of a inteval.

InputThe first line is the number of the test cases.
For each test case, the first line contain two integer n and m (n, m <= 100000), indicates the number of integers in the sequence and the number of the quaere.
The second line contains n integers, describe the sequence.
Each of following m lines contains three integers s, t, k.
s,t indicates the interval and k indicates the kth big number in interval s,t
OutputFor each test case, output m lines. Each line contains the kth big number.Sample Input
1 
10 1 
1 4 2 3 5 6 7 8 9 0 
1 3 2 
Sample Output
2

由于这个是动态查询,我们开辟nlogn*n的区间显然是不可以的,我们可以发现,每一次查询的时候只是改变了一个叶节点,然后我们画图可知一条链上最多有[lgn+2]向下取整的点被改动于是我们就可以建立一颗主席树,动态开辟节点,每一个节点使用一个左右指针就可以了。
由于数据范围比较大,我们可以采用离散化,首先对数组进行排序和去重,然后再数组里面二分原数组进行更新就可以了
然后就是一大堆细节处理啦,处理不好就会像我一样wa无数遍。
具体看代码,我这份代码应该自我感觉写的比较好看的。。
update 主席树的空间大约为nlg^2n所以空间要开辟的大一些lg1e5大约在17左右,我多开一倍(1<<5)否则会re
#pragma GCC optimize("O2")
#include<bits/stdc++.h>
#define mid (l+(r-l)/2)
#define maxn 120000 
using namespace std;
int b[maxn],a[maxn],sum[maxn<<5],n,m,sz=0,L[maxn<<5],R[maxn<<5];

void build(int &rt,int l,int r)
{
	rt=++sz,sum[rt]=0;
	if(l==r) return ;
	build(L[rt],l,mid);
	build(R[rt],mid+1,r);
}

void update(int pr,int &rt,int l,int r,int x)
{
	rt=++sz;sum[rt]=sum[pr]+1;
	L[rt]=L[pr],R[rt]=R[pr];
	if(l==r) return ;
	if(x<=mid) update(L[pr],L[rt],l,mid,x);
	else update(R[pr],R[rt],mid+1,r,x);
}

int query(int pr,int rt,int l,int r,int x)
{
	if(l==r) return l;
	int now=sum[L[rt]]-sum[L[pr]];
	if(now>=x) return query(L[pr],L[rt],l,mid,x);
	else return query(R[pr],R[rt],mid+1,r,x-now);
}

int rt[maxn];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);sz=0;
		for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];
		sort(b+1,b+n+1);
		int d=unique(b+1,b+n+1)-(b+1);
		build(rt[0],1,d);
		for(int i=1;i<=n;i++)
		{
			int x=lower_bound(b+1,b+1+d,a[i])-b;
			update(rt[i-1],rt[i],1,d,x);
		}
		while(m--)
		{
			int l,r,k;
			scanf("%d%d%d",&l,&r,&k);
			printf("%d\n",b[query(rt[l-1],rt[r],1,d,k)]);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/u013672056/article/details/76220036
今日推荐