Super Mario

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

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

题目链接:HDU 4417

题意:给你n个数组成的序列求[L,R]中小于等于H的数有多少个,序列下标从0开始

本来对于一般的线段树就直接求和query(1,1,H)即可,但是这样子显然默认的根节点为1即对整颗线段树进行查询,而题目中给的是固定的一段区间,并非朴素线段树默认的的1,N。然后就可以用到主席树了,主席树可以有很多种的区间查询求区间第K大只是其中一种而已吧,这题就是求区间内的区间求和,好像听起来很别扭,就是对一个固定区间内部进行值域求和,本题就是进行区间查询(求和),过程和普通线段树非常相似,在注释中对比了一下普通线段树的姿势……

由于H可能过大,因此要离散化再用lowerbound把H等效为某一个离散化后的高度

代码:

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define MID(x,y) ((x+y)>>1) const int N=1e5+7;
struct seg
{
int lson,rson;
int cnt;
};
seg T[N*20];
int root[N],arr[N],tot;
vector<int>vec; void init()
{
CLR(root,0);
tot=0;
vec.clear();
}
void update(int &cur,const int &ori,const int &l,const int &r,const int &val)
{
cur=++tot;
T[cur]=T[ori];
++T[cur].cnt;
if(l==r)
return ;
int mid=MID(l,r);
if(val<=mid)
update(T[cur].lson,T[ori].lson,l,mid,val);
else
update(T[cur].rson,T[ori].rson,mid+1,r,val);
}
int query(const int &S,const int &E,const int &l,const int &r,const int &x,const int &y)
{
if(x<=l&&r<=y)//l<=T[k].l&&T[k].r<=r
return T[E].cnt-T[S].cnt;//return T[k].cnt;
int mid=MID(l,r);
if(y<=mid)//r<=T[k].mid
return query(T[S].lson,T[E].lson,l,mid,x,y);
else if(x>mid)//l>T[k].mid
return query(T[S].rson,T[E].rson,mid+1,r,x,y);
else
return query(T[S].lson,T[E].lson,l,mid, x,mid)+query(T[S].rson,T[E].rson,mid+1,r, mid+1,y);
}
int main(void)
{
int T,n,m,i,l,r,h;
scanf("%d",&T);
for (int q=1; q<=T; ++q)
{
init();
scanf("%d%d",&n,&m);
for (i=1; i<=n; ++i)
{
scanf("%d",&arr[i]);
vec.push_back(arr[i]);
}
sort(vec.begin(),vec.end());
vec.erase(unique(vec.begin(),vec.end()),vec.end());
int R=vec.size();
for (i=1; i<=n; ++i)
{
arr[i]=lower_bound(vec.begin(),vec.end(),arr[i])-vec.begin()+1;
update(root[i],root[i-1],1,R,arr[i]);
}
printf("Case %d:\n",q);
for (i=0; i<m; ++i)
{
scanf("%d%d%d",&l,&r,&h);
++l;
++r;
int indx=lower_bound(vec.begin(),vec.end(),h)-vec.begin()+1;
//由于H可能过大因此只能找一个最接近的值indx来等效代替
if(vec[indx-1]!=h)
--indx;
printf("%d\n",indx? query(root[l-1],root[r],1,R,1,indx) : 0);
}
}
return 0;
}

HDU 4417 Super Mario(主席树求区间内的区间查询+离散化)的更多相关文章

  1. HDU 4417 Super Mario 主席树查询区间小于某个值的个数

    #include<iostream> #include<string.h> #include<algorithm> #include<stdio.h> ...

  2. HDU 4417 Super Mario 主席树

    分析:找一个区间里小于等于h的数量,然后这个题先离散化一下,很简单 然后我写这个题主要是熟悉一下主席树,其实这个题完全可以离线做,很简单 但是学了主席树以后,我发现,在线做,一样简单,而且不需要思考 ...

  3. HDU 4417 Super Mario(划分树问题求不大于k的数有多少)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  4. hdu 5919--Sequence II(主席树--求区间不同数个数+区间第k大)

    题目链接 Problem Description Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2 ...

  5. HDU 4417 Super Mario(划分树)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  6. HDU 4417 - Super Mario ( 划分树+二分 / 树状数组+离线处理+离散化)

    题意:给一个数组,每次询问输出在区间[L,R]之间小于H的数字的个数. 此题可以使用划分树在线解决. 划分树可以快速查询区间第K小个数字.逆向思考,判断小于H的最大的一个数字是区间第几小数,即是答案. ...

  7. SPOJ 3267 D-query(离散化+主席树求区间内不同数的个数)

    DQUERY - D-query #sorting #tree English Vietnamese Given a sequence of n numbers a1, a2, ..., an and ...

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

    把数值和查询放在一起从小到大排序,纪录每个数值的位置,当遇到数值时就更新到树状数组中,遇到查询就直接查询该区间和. #include <cstdio> #include <cstri ...

  9. HDU 4417 Super Mario(划分树+二分)

    题目链接 #include <cstdio> #include <cstring> #include <algorithm> using namespace std ...

随机推荐

  1. [Android Pro] 通过IMSI判断手机是移动、联通、电信

    TelephonyManager telManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); /** 获取 ...

  2. C# this和base

    base关键字:其用于在派生类中实现对基类公有或者受保护成员的访问,但是只局限在构造函数.实例方法和实例属性访问器中,还有指定创建派生类实例时应调用的基类构造函数. this关键字:限定被相似的名称隐 ...

  3. 如何从Apache官网下载windows版apache服务器

    参考文章:http://jingyan.baidu.com/article/29697b912f6539ab20de3cf8.html

  4. WPF入口Application

    1.WPF和 传统的WinForm 类似, WPF 同样需要一个 Application 来统领一些全局的行为和操作,并且每个 Domain (应用程序域)中只能有一个 Application 实例存 ...

  5. 实现开启和关闭android移动网络(转)

    开启和关闭移动数据网络有两种方法:一种是通过操作系统的数据库改变APN(网络接入点),从而实现开启和关闭移动数据网络,另一种是通过反射调用系统(ConnectivityManager)的setMobl ...

  6. JAVA中操作符的优先级

    一元数学比较有逻辑 三元赋值就可以! 一元操作符 数学操作符 比较操作符 逻辑操作符 三元操作符 赋值操作符

  7. 【转】cloudera新增用户权限配置

    转自 http://lookqlp.iteye.com/blog/2189119  .   配置起来较复杂,需要在有测试环境之后再进行配置测试.  之后是有上HUE的计划的,所以这个也是一定要做的. ...

  8. Xamarin.Android编译提示找不到mscorlib.dll.so文件

    Xamarin.Android编译提示找不到mscorlib.dll.so文件 错误信息:AOT module ‘mscorlib.dll.so’ not found: Cannot load lib ...

  9. DP(优化) UVALive 6073 Math Magic

    /************************************************ * Author :Running_Time * Created Time :2015/10/28 ...

  10. 海贼王之——梦想音乐

      相信和很多海粉一样,对伙伴的关照和战斗,是相当地震撼.   好东西时不时地听一下,然后感受那种刷新全身表层细胞,触电...:   音乐链接: http://v.youku.com/v_show/i ...