Super Mario:http://acm.hdu.edu.cn/showproblem.php?pid=4417
Super Mario
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 11666 Accepted Submission(s): 4856
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
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+6;
int a[maxn];//初始数组
int b[maxn];//离散化数组
int root[maxn];//定点编号
int cnt;
struct node
{
int l,r,sum;//sum表示那个位置点的个数
} sz[maxn*20]; //主席树20倍空间
void updata(int l,int r,int &x,int y,int p)//&一定要加,因为每次递归都会更新
{
sz[++cnt]=sz[y];//新加一个顶点等于原来的顶点
sz[cnt].sum++;//存放的个数加一个
x=cnt;
if(l==r)
return ;
int mid=(l+r)>>1;
if(mid>=p)
updata(l,mid,sz[x].l,sz[y].l,p);
else
updata(mid+1,r,sz[x].r,sz[y].r,p);
}
int getSum(int l,int r,int x,int y,int v)
{
if(l==r)
return sz[y].sum-sz[x].sum;
int ans=0;
int mid=(l+r)>>1;
if(mid>=v)
return getSum(l,mid,sz[x].l,sz[y].l,v);
else
return sz[sz[y].l].sum-sz[sz[x].l].sum+getSum(mid+1,r,sz[x].r,sz[y].r,v);
}
int main()
{
int t,q=1;
scanf("%d",&t);
while(t--)
{
memset(a,0,sizeof a);
memset(root ,0, sizeof root);
memset(sz,0,sizeof sz);
memset(b,0,sizeof b);
int n,m;
scanf("%d %d",&n,&m);
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);//存放数组
b[i]=a[i];//离散化数组
}
sort(b+1,b+1+n);//排序
int size=unique(b+1,b+1+n)-b-1;//去重,离散化
for(int i=1; i<=n; i++)
{
int p=lower_bound(b+1,b+1+size,a[i])-b;//查询数组a中的值,在b数组中的哪
updata(1,size,root[i],root[i-1],p);//更新那个位置的值
}
printf("Case %d:\n",q++);
for(int i=1; i<=m; i++)
{
int x,y,k;
scanf("%d %d %d",&x,&y,&k);
k=upper_bound(b+1,b+size+1,k)-b-1;
if(k==0) printf("0\n");
else
printf("%d\n",getSum(1,size,root[x],root[y+1],k));//查询结果[X-Y]第K小
}
}
}
来源:https://blog.csdn.net/Ccqingkong/article/details/99605500