HDU 1025

题意:一个国王,他的城市对齐的建在两根平行的线上。城市有编号1-n(两边一样)。

输入:每次先输入一个数n,代表两边均有n个城市,接下来n行,每行两个整数a,b,表示A线上的城市a和B线上的城市b之间有一条马路。这样,马路之间便很有可能出现交点,国王要求你去除一些马路,使得最终留下的马路两两之间没有交点,并在此前提下尽量多的留下马路。

输出:最多留下的马路的数量。

题解:最长递增子序列

很典型,自己开始想只想到了dp,却没想到用二分,或者说,重点是没有想到用一个B[n]数组作为辅佐,来记录序列长度为k的序列中,最小序列尾的值B[k]。这个辅佐数组非常重要,因为它有单调递增的性质(因为如果有B[3]>B[4],那么在得到B[4]的序列中的第三个数B[4]3也会小于B[4]并且小于B[3],即有B[4]3<B[4]<B[3],这有与B数组的定义相悖),因为这个性质我们可以使用二分来进行查找,而且我们每次对于这个数组的修改插入只需在原数组上修改或在数组末尾增添,而这些都是o(1)的。

关于二分,做此题也算是复习了一下。二分总得来说就是通过每次刷选一半的区间,让区间左右两端的值都逼近目标值。

然后题目的输出格式要注意,有road(s)的区别。

以下为代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=5e5+10;
int num[maxn],B[maxn];
int len;
int find_pos(int a,int l,int r){
    while(l<=r){
        int mid=(l+r)/2;
        if(B[mid]>a){
            r=mid-1;
        }
        else l=mid+1;
    }
    if(l>len) len=l;
    return l;
}
int main(){
    int n;
    int x,y;
    int icount=1;
    while(scanf("%d",&n)!=EOF){
         len=1;
         for(int i=0;i<n;++i){
            scanf("%d%d",&x,&y);
            num[x]=y;
         }
         B[1]=num[1];
         for(int i=2;i<=n;++i){
            int y=num[i];
            B[find_pos(y,1,len)]=y;
         }
         if(len==1)
         printf("Case %d:\nMy king, at most 1 road can be built.\n\n",icount++);
         else printf("Case %d:\nMy king, at most %d roads can be built.\n\n",icount++,len);
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值