HDU 3193 Find the hotel(RMQ)

558 篇文章 0 订阅
273 篇文章 0 订阅

HDU 3193 Find the hotel(RMQ)

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

      1    10

      2    5

      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查询.由于pd可能为0,所以我们在读入的时候把所有pd值加1,然后最后输出的时候把所有p,d值减1即可.

      本算法总的复杂度是O(nlogn).

AC代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN =10000+100;
int a[MAXN];
int dmin[MAXN][20];
void initMin(int n,int d[])
{
    for(int i=0; i<=n; i++)dmin[i][0]=d[i];
    for(int j=1; (1<<j)<=n; j++)
        for(int i=1; i+(1<<j)-1<=n; i++)
            dmin[i][j] = min(dmin[i][j-1] , dmin[i+(1<<(j-1))][j-1]);
}
int getMin(int L,int R)
{
    int k=0;
    while((1<<(k+1))<=R-L+1)k++;
    return min(dmin[L][k] , dmin[R-(1<<k)+1][k]);
}
struct node
{
    int p,d;
    bool operator <(const node &b)const
    {
        return p<b.p || (p==b.p && d<b.d);
    }
} node1[MAXN],node2[MAXN];
int main()
{
    int n;
    while(scanf("%d",&n)==1&&n)
    {
        for(int i =0; i<=10000+100; i++)
            a[i]=1000000;
        for(int i=1; i<=n; i++)
        {
            int p,d;
            scanf("%d%d",&p,&d);
            p++;
            d++;
            node1[i].p=p;
            node1[i].d=d;
            a[p] = min(a[p],d);
        }
        initMin(MAXN,a);
        int cnt=0;
        for(int i=1; i<=n; i++)
        {
            int p,d;
            p = node1[i].p;
            d = node1[i].d;
            if(p==1)//这个需要特殊处理,否则下面会getMin(1,0)了
            {
                node2[++cnt]  =node1[i];
            }
            else
            {
                int d_min = getMin(1,p-1);
                if(d<=d_min)
                {
                    node2[++cnt]  =node1[i];
                }
            }
        }
        sort(node2+1,node2+1+cnt);
        printf("%d\n",cnt);
        for(int i=1; i<=cnt; i++)
            printf("%d %d\n",node2[i].p-1,node2[i].d-1);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值