1. 程式人生 > >4417 Super Mario —— 線段樹 離線處理

4417 Super Mario —— 線段樹 離線處理

Super Mario

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


 

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

題意:

問L到R之間有幾個數小於H

思路:

離線處理,按照詢問的高度從小到大依次查詢,每次查詢前將所有小於等於當前查詢高度的數都加進線段樹中,然後直接查詢就可以了。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
struct node
{
	int l,r;
	int w;
};
struct node tree[400010];
struct block
{
	int h,id;
};
bool cmp1(const block &a,const block &b)
{
	return a.h<b.h;
}
struct block b[100010];
struct qq
{
	int l,r,h;
	int id;
};
struct qq ques[100010];
bool cmp2(const qq &a,const qq &b)
{
	return a.h<b.h;
}
int n,m;
int casnum=1;
int ans[100010];
void built(int i,int l,int r)
{
	tree[i].l=l;
	tree[i].r=r;
	tree[i].w=0;
	if(l==r)
	return;
	int mid=(l+r)>>1;
	built(i<<1,l,mid);
	built(i<<1|1,mid+1,r);
}
void updata(int i,int x)
{
	if(tree[i].l==tree[i].r)
	{
		tree[i].w++;
		return;
	}
	int mid=(tree[i].l+tree[i].r)>>1;
	if(x<=mid)
	updata(i<<1,x);
	else 
	updata(i<<1|1,x);
	tree[i].w=tree[i<<1].w+tree[i<<1|1].w;
}
int query(int i,int l,int r)
{
	if(tree[i].l==l&&tree[i].r==r)
	{
		return tree[i].w;
	}
	int mid=(tree[i].l+tree[i].r)>>1;
	if(r<=mid)
	return query(i<<1,l,r);
	else if(l>mid)
	return query(i<<1|1,l,r);
	else
	return query(i<<1,l,mid)+query(i<<1|1,mid+1,r);
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		built(1,1,n);
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&b[i].h);
			b[i].id=i;
		}
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d%d",&ques[i].l,&ques[i].r,&ques[i].h);
			ques[i].l++;
			ques[i].r++;
			ques[i].id=i;
		}
		sort(b+1,b+1+n,cmp1);
		sort(ques+1,ques+1+m,cmp2);
		int i=1,j=1;
		for(;j<=m;j++)
		{
			while(i<=n&&b[i].h<=ques[j].h)
			{
				updata(1,b[i].id);
				i++;
			}
			ans[ques[j].id]=query(1,ques[j].l,ques[j].r);
		}
		printf("Case %d:\n",casnum++);
		for(int i=1;i<=m;i++)
		{
			printf("%d\n",ans[i]);
		}
	}
}