Super Mario(線段樹 + 離散化)

Super Mario
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7756 Accepted Submission(s): 3322

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個數 然後又m個查詢命令 查l,r 區間內有多少比h小的個數
第一次做離散化的處理 給我感覺就是我們並不是一開始就建樹 而是在處理的過程中進行動態建樹 其實這裏還可以用主席樹求第k個大的數是什麼(可惜主席樹還不會…….) 所以只能離散化處理了 首先我們需要將n個數的下標和值進行存儲在一個結構體內 然後再講待查詢的數存儲在另外一個結構體內 記住下標一定要存儲 因爲我們在最後輸出答案時需要根據下標進行輸出然後我們在將兩個結構體數組按照高度從小到大進行排序 然後進行一一的比較 如果brick[i].h

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

using namespace std;
#define MAXN 100007
struct Lnode
{
    int pos;//記錄當前節點位置
    int h;//記錄當前節點的高度
}brick[MAXN];
struct Tnode
{
    int pos;
    int h;
    int l;
    int r;
}node[MAXN];
int n,m;
int ans[MAXN];
int sum[MAXN*4];
bool mycmp(struct Lnode a,struct Lnode b)//高度從小到大進行排序
{
    return a.h < b.h;
}
bool cmp(struct Tnode a, struct Tnode b)
{
    return a.h < b.h;
}
void insertNode(int pos,int rt,int l,int r)
{
    if(l==r)
    {
        sum[rt] =1;
        return;
    }
    int mid = (l+r)/2;
    if(pos<= mid)
        insertNode(pos,rt*2,l,mid);
    else
        insertNode(pos,rt*2+1,mid+1,r);
    sum[rt] = sum[rt*2] + sum[rt*2+1];
}
int query(int l,int r,int L,int R,int rt)
{
    if(l==L && r == R)
    {
        return sum[rt];
    }
    int mid = (L+R)/2;
    if(r <= mid)
        return query(l,r,L,mid,rt*2);
    else if(l>mid)
        return query(l,r,mid +1,R,rt*2+1);
    else
        return query(l,mid,L,mid,rt*2) + query(mid +1,r,mid+1,R,rt*2+1);
}
int main()
{
    int ncase;
    scanf("%d",&ncase);
    int cnt =1;
    while(ncase--)
    {
        printf("Case %d:\n",cnt++);
        scanf("%d%d",&n,&m);
        memset(brick,0,sizeof(brick));
        memset(node,0,sizeof(node));
        memset(ans,0,sizeof(ans));
        memset(sum,0,sizeof(sum));
        for(int i =1;i<= n;i++)
        {
            scanf("%d",&brick[i].h);
            brick[i].pos = i;
        }
        for(int i =1;i<=m;i++)
        {
            scanf("%d%d%d",&node[i].l,&node[i].r,&node[i].h);
            node[i].pos = i;
            node[i].l++;
            node[i].r++;
        }
        sort(brick +1 ,brick +n+1,mycmp);
        sort(node +1 ,node +m+1,cmp);
        int j =1;
        for(int i =1;i<= n;)
        {
            if(brick[i].h > node[j].h)//如果當前節點比要查詢的節點大 那麼就不需要進行插入了 如果比其結果還要小就需要進行插入
            {
               ans[node[j].pos] = query(node[j].l,node[j].r,1,n,1);
               j++;
               if(j>m)
                break;
            }
            else
            {
                insertNode(brick[i].pos,1,1,n);
                i++;
            }
        }
        for(;j<=m;j++)
        {
            ans[node[j].pos] = query(node[j].l,node[j].r,1,n,1);
        }
        for(int i =1;i<=m;i++)
            printf("%d\n",ans[i]);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章