Find the hotel(HDU-3193) (RMQ)

Find the hotel

Problem Description
Summer again! Flynn is ready for another tour around. Since the tour would take three or more days, it is important to find a hotel that meets for a reasonable price and gets as near as possible!
But there are so many of them! Flynn gets tired to look for any. It’s your time now! Given the (pi, di) for a hotel hi, where pi stands for the price and di is the distance from the destination of this tour, you are going to find those hotels, that either with a lower price or lower distance. Consider hotel h1, if there is a hotel hi, with both lower price and lower distance, we would discard h1. To be more specific, you are going to find those hotels, where no other has both lower price and distance than it. And the comparison is strict.

Input
There are some cases. Process to the end of file.
Each case begin with N (1 <= N <= 10000), the number of the hotel.
The next N line gives the (pi, di) for the i-th hotel.
The number will be non-negative and less than 10000.

Output
First, output the number of the hotel you find, and from the next line, print them like the input( two numbers in one line). You should order them ascending first by price and break the same price by distance.

Sample Input
3
15 10
10 15
8 9
Sample Output
1
8 9

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=3193

題目大意:
給你n個旅館的p(價格)和d(距離值),然後要你輸出所有的“目的旅館”。如果對於旅館i來說,沒有其他任何一個旅館的px和dx值同時小於pi和di。那麼旅館i可以算一個“目的旅館”。
輸出:
先輸出目的旅館的個數。
再按p從小到大(如p相同,d從小到大)的順序輸出所有目的旅館的p和d值。

題目分析:
本題的要求很特殊,注意是要一個旅館的p和d屬性同時小於另外一個旅館才能判斷第二個旅館不是目的旅館。
看下面的輸入例子: 輸出卻也是:
3 ——————> 3
1 10 ——————> 1 10
2 5 ——————> 2 5
2 6 ——————> 2 6
本題採用標記法,把二維屬性p和d變成一維,只考慮d就行。首先讀入所有的旅店,然後對於每個讀入的旅店更新一個數組a[],
其中a[p]=d表示所有價格爲p的旅店中最短的距離是d.
然後再掃描一遍所有旅店,假設當前掃描到的旅店爲(pi , di),那麼如果我們已經知道了價格小於pi的所有旅店中距離最小值爲d且這個(d小於di),那麼肯定拋棄(pi , di) ,否則留下(pi, di).
上述查詢最小d值的過程就是getMin(0,pi-1).所以需要RMQ查詢.由於p和d可能爲0,所以我們在讀入的時候把所有p和d值加1,然後最後輸出的時候把所有p,d值減1即可.
本算法總的複雜度是O(nlogn).
**

代碼:

**

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
typedef long long LL;
const int N=10099;
int dp[N][30],d[N];  //這裏用d數組存儲p價格的最短距離。
struct sky
{
    int p;
    int d;
}a[N],num[N];
bool cmp(sky a,sky b)
{
    if(a.p!=b.p)
        return a.p<b.p;
    else
        return a.d<b.d;
}
void ST(int n)
{
    for(int i=0;i<n;i++)
        dp[i][0]=d[i];
    for(int j=1;(1<<j)<=n;j++)
    {
        for(int i=0 ; i+(1<<j)-1<n ;i++)
        {
            dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
        }
    }
}
int RMQ(int l,int r)
{
    int k=log(r-l+1.0)/log(2.0);
    int a=dp[l][k];
    int b=dp[r-(1<<k)+1][k];
    return min(a,b);
}
int main()
{
    int n,k;
    while(scanf("%d",&n)!=EOF)
    {
        k=0;
        memset(a,0,sizeof(a));
        memset(num,0,sizeof(num));
        memset(d,0x3f,sizeof(d));
        int p,dis;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&p,&dis);
            a[i].p=p;
            a[i].d=dis; 
            d[p]=min(d[p],dis);
        }
        sort(a,a+n,cmp);
        ST(N); //這裏傳入N 就可以以爲價格最高也不會超過N 
        //但是不知到爲什麼這裏傳入n也對,誰知道告訴我一下
        num[k].p=a[0].p;
        num[k++].d=a[0].d;
        for(int i=1;i<n;i++)
        {
            if(a[i].p==0) // 如果價錢爲 0 的話要特判,此時不存在價格比 0 還小的
            {
                num[k++]=a[i];
                continue;
            }
            int x=RMQ(0,a[i].p-1);
            if(a[i].d>x) //如果在0到p-1的 價格能找到距離比這個旅館距離小的就跳過
                continue;
            num[k].p=a[i].p;
            num[k++].d=a[i].d;
        }
        printf("%d\n",k);
        for(int i=0;i<k;i++)
        {
            printf("%d %d\n",num[i].p,num[i].d);
        }
    }
    return 0;
}

發佈了33 篇原創文章 · 獲贊 12 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章