您的位置:首页 > 理论基础 > 数据结构算法

HDU 4417 超级马里奥 数据结构+利用树状数组进行快速统计+多维统计转换

2016-08-03 15:01 417 查看
HDU 4417 超级马里奥

Time Limit:1000MS    Memory Limit:32768KB    64bit IO Format:%I64d & %I64u

SubmitStatusPracticeHDU
4417

Description

马里奥是一个举世闻名的管道工,他的跳跃能力让我们钦佩。在一条长度为n的道路上,在每个整数点i的位置都有一个高度为hi的障碍物。现在的问题是:假设马里奥可以跳跃的最高高度为H,在道路的[L,R]
区间内他可以跳跃过的障碍物有多少个(不要考虑他被挡住)?

Input

第一行是数据个数T。
对于每组数据:
第一行包含两个整数n, m (1 <= n <=10^5, 1 <= m <= 10^5), n
表示道路的程度, m是询问的个数.
第二行包含n个整数,表示每个障碍物的高度,
高度范围是 [0, 1000000000].
接着 m 行,每行3个整数 L, R,H.( 0 <= L <= R < n 0 <= H <= 1000000000.)

Output

对于每组数据, 先输出"Case X: " (
X表示组数) 然后有m行,
每行包含一个整数. 第i个整数表示第i个询问的答案。
4000

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

解题思路:
这题是一个利用树状数组或线段树进行快速统计的一个题,题目不难但是不是很好想起来
比赛的时候没有想起来,简直被自己蠢哭了,唉。
1,首先这是一个经典的统计问题,求区间内小于某个数的个数有多少
2,这是一个二维统计问题,有两个变量需要考虑一个是区间,另一个是高度
3,因为区间不好通过排序消除影响,所以就是通过高度的排序消除高度的影响了
4,把询问的高度按照从小到大排序,顺序取出每一个高度h,然后把这条路上的所有的小于
这个高度的填充进(树状数组或线段树)对应的下标那里加一,然后对于h的查询就很好算了
5,简单统计一定要想到这种做法。。。。
下面代码用的树状数组。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 100005;
int n ;
struct node{
int id;
int x ;
int y ;
int h ;
int num;
};
node arry[maxn] ;
int C[maxn] ;
struct node2{
int id;
int h ;
};
node2 s[maxn] ;
int lowbit(int x){return x&-x;}
int sum(int x){
int ret = 0 ;
while(x>0){
ret+=C[x];
x-=lowbit(x);
//printf("shgfaj");
//printf("ret = %d\n",ret);
}
//printf("ret = %d\n",ret);
return ret ;
}
void add(int x,int d){
while(x<=n){
C[x]+=d ;
x+=lowbit(x) ;
//printf("asd");
}
return ;
}

bool cmp(node a,node b){
return a.h<b.h ;
}
bool cmp2(node a,node b){
return a.id<b.id ;
}
bool cmp3(node2 a,node2 b){
return a.h<b.h ;
}

int main() {
int m;
int T ,cas=1;
//freopen("in.txt","r",stdin);
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&s[i].h);
s[i].id = i ;
}
for(int i=1;i<=m;i++){
scanf("%d%d%d",&arry[i].x,&arry[i].y,&arry[i].h);
arry[i].x++ ;
arry[i].y++ ;
arry[i].id = i ;
}
sort(arry+1,arry+m+1,cmp) ;
sort(s+1,s+n+1,cmp3);

//        for(int i=1;i<=m;i++){
//            printf("%d ",arry[i].h);
//        }printf("\n");
//        for(int i=1;i<=m;i++){
//            printf("%d ",s[i].h);
//        }printf("\n");

memset(C,0,sizeof(C));
int j=1;
for(int i=1;i<=m;i++){
for(;j<=n&&s[j].h<=arry[i].h;j++){
add(s[j].id,1);
//printf("id = %d\n",s[j].id);
}
//printf("i = %d\n",i);
int as = sum(arry[i].y) ;
//printf("sssss = %d\n",as);
arry[i].num = sum(arry[i].y)-sum(arry[i].x-1) ;

}
//printf("max = %d\n",sum(n));
sort(arry+1,arry+m+1,cmp2) ;
printf("Case %d:\n",cas++);
for(int i=1;i<=m;i++){
printf("%d\n",arry[i].num);
}

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: