HDU-4417 Super Mario (主席树)

Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory. Now the poor princess is in trouble again and Mario needs to save his lover. We regard the road to the boss’s castle as a line (the length is n), on every integer point i there is a brick on height hi. Now the question is how many bricks in [L, R] Mario can hit if the maximal height he can jump is H.
Input
The first line follows an integer T, the number of test data.
For each test data:
The first line contains two integers n, m (1 <= n <=10^5, 1 <= m <= 10^5), n is the length of the road, m is the number of queries.
Next line contains n integers, the height of each brick, the range is [0, 1000000000].
Next m lines, each line contains three integers L, R,H.( 0 <= L <= R < n 0 <= H <= 1000000000.)
Output
For each case, output "Case X: " (X is the case number starting from 1) followed by m lines, each line contains an integer. The ith integer is the number of bricks Mario can hit for the ith query.
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


题意:给你n个数,m次询问,每次询问l,r区间内小与h的数

解题思路:这也是一道主席树的模板题,只是一开始我自己写的时候对query函数的修改一直有bug,然后在网上看了看别人的板子,主席树只要理解了,写起来应该是挺容易的。它关键在于每个点更新的时候“新建”一个树,当然直接建会空间爆炸,但新建的这个树,只有新建的logn个点发生变化,其它的点可以直接引用上一次的,因为没有发生改变。这样每次新建只多出logn的空间,在有限的空间内做到了可持久化。把每次新建树的权值记录下来,但考虑到新建节点的下表问题,我们的左右儿子是用lson和rson特别储存下标的也就是说没有原来那种*2和 *2+1的操作。
下面给你们放一张图:
序列4 3 2 3 6 1的建主席树过程
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(图是别的博主那里拿的https://blog.csdn.net/ModestCoder_/article/details/90107874

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=100010;
int a[maxn],b[maxn],tot,rt[maxn];
struct node{
    int sz,lson,rson;
}tree[maxn<<5];
//空间开到nlogn,在int范围内的n,longn最大差不多就是32左右,所以用maxn<<5
int build(int l,int r)
{
    int id=++tot;
    tree[id].sz=0;
    if(l==r)
        return id;
    int mid=(l+r)>>1;
    tree[id].lson=build(l,mid);
    tree[id].rson=build(mid+1,r);
    return id;
}
int update(int rt,int pos,int l,int r)
{
    int id=++tot;
    tree[id].sz=tree[rt].sz;
    tree[id].lson=tree[rt].lson;
    tree[id].rson=tree[rt].rson;
    //继承上一节点
    if(l==r){
        tree[id].sz++;
        return id;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)
        tree[id].lson=update(tree[id].lson,pos,l,mid);
    else
        tree[id].rson=update(tree[id].rson,pos,mid+1,r);
    tree[id].sz=tree[tree[id].lson].sz+tree[tree[id].rson].sz;
    return id;
}
int query(int pre,int rt,int l,int r,int L,int R)
{
    if(L>R)
        return 0;
    if(l>=L&&r<=R)
        return tree[rt].sz-tree[pre].sz;
    int mid=(l+r)>>1;
    int ans=0;
    if(mid>=L)
        ans+=query(tree[pre].lson,tree[rt].lson,l,mid,L,R);
    if(mid<R)
        ans+=query(tree[pre].rson,tree[rt].rson,mid+1,r,L,R);
    return ans;
}
int main()
{
    int t;
    int c=1;
    scanf("%d",&t);
    while(t--){
        printf("Case %d:\n",c++);
        int n,m,num,pos,l,r,h;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            b[i]=a[i];
        }
        sort(b+1,b+1+n);
        num=unique(b+1,b+1+n)-b-1;//离散化
        tot=0;
        rt[0]=build(1,num);
        for(int i=1;i<=n;i++){
            pos=lower_bound(b+1,b+1+num,a[i])-b;
            rt[i]=update(rt[i-1],pos,1,num);
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&l,&r,&h);
            pos=upper_bound(b+1,b+1+num,h)-b-1;
            printf("%d\n",query(rt[l],rt[r+1],1,num,1,pos));
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44003265/article/details/103990361