HDU 4417 Super Mario(离线 + 树状数组)

博客围绕Mario救公主的题目展开,题目是在长度为n的路上,每个整数点i有高度为hi的砖块,求在区间[L, R]中Mario最大跳跃高度为H时能击中的砖块数。给出两种解题思路,一是按数值大小回归数组离线统计1的个数,二是增加新区间转化结果计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:
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.

思路:
        做法一:按 数值大小不断的回归数组,离线统计区间中 1的个数。
        做法二:对于每个 L != 0 的区间,我们都增加一个新区间 [0,L-1],这样我们结果就转化为区间[0,R] 的值 减去 [0,L-1]的值 .比上述方法慢 30ms 左右 (也有可能自己写搓了 )。

参考代码

#include <iostream>
#include <algorithm>
using namespace std;
struct QJ
{
    int l,r,h;
    int num;
    int f;
};
QJ s[100050];

int n,len,m;
int a[100050];
int v[100050];
int c[100050];
int ans[100050];

bool cmp(const QJ& a,const QJ& b) {
    return a.r == b.r? a.l<b.l:a.r<b.r;
}

int lowbit(int x) {
    return x&-x;
}

void update(int pos,int d) {
    while(pos<=len) {
        c[pos] += d;
        pos += lowbit(pos);
    }
    return ;
}

int getsum(int pos) {
    int ans = 0;
    while(pos>0) {
        ans += c[pos];
        pos -= lowbit(pos);
    }
    return ans;
}

int main() {
    int t;int cases = 1;
    cin>>t;
    while(t--) {
        int now = 0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) {
            scanf("%d",&a[i]);
            v[i-1] = a[i];
            c[i] = 0;
        }
        sort(v,v+n);
        len = unique(v,v+n) -v;
        for(int i=0;i<m;i++) {
            ans [i] = 0;
            scanf("%d%d%d",&s[now].l,&s[now].r,&s[now].h);
            s[now].l++;s[now].r++;
            s[now].num = i; s[now].f = 1;
            now++;
            if(s[now-1].l!=1) {
                s[now].l = 1;
                s[now].r = s[now-1].l-1;
                s[now].h = s[now-1].h;
                s[now].num=i;
                s[now].f = -1;
                now++;
            }
        }
        int pre = 0;
        sort(s,s+now,cmp);
        for(int i=1;i<=n;i++) {
            if(pre == now) break;
            int temp = lower_bound(v,v+len,a[i])-v +1;
            update(temp,1);
            while(pre<now&& s[pre].r<=i) {
                int temps = upper_bound(v,v+len,s[pre].h) - v +1; 
                ans[s[pre].num] += s[pre].f * (getsum(temps-1));
                // cout <<  s[pre].num << ' '<<ans[s[pre].num]<<endl;
                pre++;
            }
        }
        printf("Case %d:\n",cases++);
        for(int i=0;i<m;i++) {
            printf("%d\n",ans[i]);
        }
    }    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值