Hdu4417 Super Mario(主席树+离散化)

来源:互联网 发布:淘宝联盟用红包有返利 编辑:程序博客网 时间:2024/05/22 13:53

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

题目大意:给你一个长度为n的数组,数组下标从0~n-1,然后有m次询问,询问区间l~r内有多少个数小于等于h。

这题一道典型的主席树题目,先对初始高度离散化,再将离散化后的权值存入主席树中,询问的时候对h也进行离散化,最后只要将第r+1棵树中小于等于h的数目减去第l棵树中小于等于h的数目即为答案。

然而按这个方法写了之后却狂WA不止,最后才发现在对询问的h离散化的时候没有考虑它有没有在初始高度中出现过,改了之后终于AC了。

#include<map>#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int N=1e5;int tot,cnt;int val[N+100],list[N+100],root[N+100],ls[N*20+100],rs[N*20+100],sum[N*20+100];map<int,int>mp;int read(){    int x=0,f=1;char ch=getchar();    for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;    for (;ch>='0'&&ch<='9';ch=getchar())    x=x*10+ch-'0';    return x*f;}void insert(int &k,int p,int l,int r,int x){    k=++tot;     sum[k]=sum[p]+1;    ls[k]=ls[p]; rs[k]=rs[p];    if (l==r)   return;    int mid=(l+r)>>1;    if (x<=mid) insert(ls[k],ls[p],l,mid,x);    else    insert(rs[k],rs[p],mid+1,r,x);}int get(int x,int y,int l,int r,int t){    if (r<=t)   return sum[y]-sum[x];    if (l==r)   return 0;    int mid=(l+r)>>1;    if (t<=mid) return get(ls[x],ls[y],l,mid,t);    else    return sum[ls[y]]-sum[ls[x]]+get(rs[x],rs[y],mid+1,r,t);}int main(){    int t=read();    for (int tt=1;tt<=t;tt++){        printf("Case %d:\n",tt);        tot=cnt=0;        int n=read(),m=read();        mp.clear();        for (int i=1;i<=n;i++){            val[i]=read();            list[i]=val[i];            if (!mp[val[i]])    mp[val[i]]=++cnt;        }        sort(list+1,list+1+n);        int T=unique(list+1,list+1+n)-list-1;        for (int i=1;i<=n;i++)  val[i]=lower_bound(list+1,list+T+1,val[i])-list;        for (int i=1;i<=n;i++)  insert(root[i],root[i-1],1,T,val[i]);        for (int i=1;i<=m;i++){            int x=read(),y=read(),t=read();            if (!mp[t]) t=lower_bound(list+1,list+T+1,t)-list-1;            else    t=lower_bound(list+1,list+T+1,t)-list;            //开始只用了 t=lower_bound(list+1,list+1+T,t)-list 便WA了很久            printf("%d\n",get(root[x],root[y+1],1,T,t));        }    }    return 0;}
原创粉丝点击