hdu 4417 Super Mario(主席树)

题目链接:hdu 4417 Super Mario

Sample Input
1
10 10
0 5 2 7 5 4 3 8 7 7 
2 8 6
3 5 0
1 3 1
1 9 4
0 1 0
3 5 5
5 5 1
4 6 3
1 5 7
5 7 3
 

Sample Output
Case 1:
4
0
0
3
1
2
0
1
5
1

 题意:给一个数组,求区间中小于等于h的数字个数

思路:裸的主席树,第一次用大致说一下自己的理解

主席树就是很多的线段树,当一个点更新的时候(上图的5更新),影响的是一条链(1-2-5),主席树保留了不需要更新的结点,第i棵线段树维护1~i的区间信息

 这一题中,0 5 2 7 5 4 3 8 7 7,离散化后得 0 2 3 4 5 7 8对应下标1 2 3 4 5 6 7,在insert操作结束之后会得到下图所示的树,圆圈中的数字表示这个区间中的数字个数,存储在size[i]

 要记住size存储的是数字个数,叶子结点是排序后离散化的下标,即权值,其他的写法的改变,按照线段树的写法来即可

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 100005

int root[N];//root[i]表示第i课线段树 
int size[N*25],lchild[N*25],rchild[N*25];
int tot;

void insert(int last,int cur,int L,int R,int k) //单点更新 
{
    size[cur]=size[last]+1;//将前一个树的信息复制过来 
    lchild[cur]=lchild[last];
    rchild[cur]=rchild[last]; 
    if(L==R)return ;
    int mid=L+R>>1;
    if(k<=mid) insert(lchild[last],lchild[cur]=++tot,L,mid,k);//对于需要更改的节点都需要新增节点
    else insert(rchild[last],rchild[cur]=++tot,mid+1,R,k);
}
int query(int last,int cur,int l,int r,int L,int R)
{
	if(l>r)return 0;
	if(L==l&&r==R){
		return size[cur]-size[last];
	}
	int mid=(L+R)>>1;
	if(l>mid)return query(rchild[last],rchild[cur],l,r,mid+1,R);
	else if(r<=mid)return query(lchild[last],lchild[cur],l,r,L,mid);
	else return query(rchild[last],rchild[cur],mid+1,r,mid+1,R)+query(lchild[last],lchild[cur],l,mid,L,mid);
}
int a[100005];
int b[100005];
int main(){
	int t;
	scanf("%d",&t);
	int c=1;
	while(t--){
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
			b[i]=a[i];
		}
		sort(b+1,b+n+1);//排序 
		int nn=unique(b+1,b+n+1)-b-1;//去重
		//上面是在离散化处理 
		tot=0;
		for(int i=1;i<=n;i++){
			int k=lower_bound(b+1,b+nn+1,a[i])-b;//找到a[i]在整个数列中是第几大
			insert(root[i-1],root[i]=++tot,1,nn,k);
		}
		printf("Case %d:\n",c++);
		for(int i=1;i<=m;i++){
			int l,r,h;
			scanf("%d%d%d",&l,&r,&h);
			l++;r++;
			int k=upper_bound(b+1,b+1+nn,h)-b-1;//找到h在整个数列中是第几大 
			printf("%d\n",query(root[l-1],root[r],1,k,1,nn)); 
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/yz467796454/article/details/81487472