hdu 4417 Super Mario (主席树+离线)

本文介绍了一种使用主席树优化的区间查询问题解决方案,应用于SuperMario游戏中的路径挑战。通过预处理不同高度的砖块分布,实现高效查询马里奥在特定路径与跳跃高度下可击打的砖块数量。

Super Mario

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8196    Accepted Submission(s): 3453


Problem Description
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

 
110 100 5 2 7 5 4 3 8 7 7 2 8 63 5 01 3 11 9 40 1 03 5 55 5 14 6 31 5 75 7 3
 

Sample Output

 
Case 1:4003120151
 

Source
 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:   6263  6262  6261  6260  6259 
 

题意:

给了一个区间,区间上每个点的石块有不同的高度,下面有M次询问,l,r,h代表马里奥在[l,r]区间以h为最大高度能撞到的石块个数。

思路:

用主席树来写,将插入和查询操作放在一起按照高度排一个序,这样就可以免去二分查找了。然后分别按照插入和查找来不同处理数据。

PS:再不敢把l,r放到结构体里了,疯狂MLE,还以为是卡主席树QAQ|

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn=1e5+5;
using namespace std;
int ans[maxn],root[maxn];
int cnt;
struct node
{
    int ls,rs,sum;
}tr[maxn*20];
struct data
{
    int l,r,id,f,h;
}q[2*maxn];
bool cmp(data a,data b)
{
    if(a.h!=b.h)
        return a.h<b.h;
    return a.f<b.f;
}
int build(int l,int r)
{
    int num=++cnt;
    if(l==r) return num;
    int mid=(l+r)/2;
    tr[num].ls=build(l,mid);
    tr[num].rs=build(mid+1,r);
    return num;
}
int update(int l,int r,int pre,int x)
{
    int num=++cnt;
    tr[num]=tr[pre];
    tr[num].sum++;
    if(l==r) return num;
    int mid=(l+r)/2;
    if(x<=mid) tr[num].ls=update(l,mid,tr[pre].ls,x);
    else tr[num].rs=update(mid+1,r,tr[pre].rs,x);
    return num;
}
int query(int l,int r,int num,int x,int y)
{
    if(x<=l&&r<=y) return tr[num].sum;
    int sum=0;
    int mid=(l+r)/2;
    if(x<=mid) sum+=query(l,mid,tr[num].ls,x,y);
    if(y>mid) sum+=query(mid+1,r,tr[num].rs,x,y);
    return sum;
}
int main()
{
    int t,n,m,cas=1,res;
    scanf("%d",&t);
    while(t--)
    {
        cnt=0,res=0;
        memset(tr,0,sizeof(tr));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&q[i].h);
            q[i].id=i;
            q[i].f=0;
        }
        for(int i=n+1;i<=n+m;i++)
        {
            scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].h);
            q[i].l++,q[i].r++;
            q[i].f=1;
            q[i].id=i-n;
        }
        sort(q+1,q+1+n+m,cmp);
        root[0]=build(1,n);
        for(int i=1;i<=n+m;i++)
        {
            if(q[i].f==0)
            {
                root[++res]=update(1,n,root[res-1],q[i].id);
            }
            else
            {
                ans[q[i].id]=query(1,n,root[res],q[i].l,q[i].r);
            }
        }
        printf("Case %d:\n",cas++);
        for(int i=1;i<=m;i++)
        {
            printf("%d\n",ans[i]);
        }
    }
    return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值