zoukankan      html  css  js  c++  java
  • HDU 1025 Constructing Roads In JGShining's Kingdom(最长上升子序列的长度)

    Constructing Roads In JGShining's Kingdom

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 7192    Accepted Submission(s): 2103


    Problem Description
    JGShining's kingdom consists of 2n(n is no more than 500,000) small cities which are located in two parallel lines.

    Half of these cities are rich in resource (we call them rich cities) while the others are short of resource (we call them poor cities). Each poor city is short of exactly one kind of resource and also each rich city is rich in exactly one kind of resource. You may assume no two poor cities are short of one same kind of resource and no two rich cities are rich in one same kind of resource.

    With the development of industry, poor cities wanna import resource from rich ones. The roads existed are so small that they're unable to ensure the heavy trucks, so new roads should be built. The poor cities strongly BS each other, so are the rich ones. Poor cities don't wanna build a road with other poor ones, and rich ones also can't abide sharing an end of road with other rich ones. Because of economic benefit, any rich city will be willing to export resource to any poor one.

    Rich citis marked from 1 to n are located in Line I and poor ones marked from 1 to n are located in Line II.

    The location of Rich City 1 is on the left of all other cities, Rich City 2 is on the left of all other cities excluding Rich City 1, Rich City 3 is on the right of Rich City 1 and Rich City 2 but on the left of all other cities ... And so as the poor ones.

    But as you know, two crossed roads may cause a lot of traffic accident so JGShining has established a law to forbid constructing crossed roads.

    For example, the roads in Figure I are forbidden.



    In order to build as many roads as possible, the young and handsome king of the kingdom - JGShining needs your help, please help him. ^_^
     
    Input
    Each test case will begin with a line containing an integer n(1 ≤ n ≤ 500,000). Then n lines follow. Each line contains two integers p and r which represents that Poor City p needs to import resources from Rich City r. Process to the end of file.
     
    Output
    For each test case, output the result in the form of sample.
    You should tell JGShining what's the maximal number of road(s) can be built.
     
    Sample Input
    2 1 2 2 1 3 1 2 2 3 3 1
     
    Sample Output
    Case 1: My king, at most 1 road can be built. Case 2: My king, at most 2 roads can be built.
    Hint
    Huge input, scanf is recommended.
     
    Author
    JGShining(极光炫影)
     
     

    解题报告:就是求最长上升子序列,一开始用的普通办法求的!直接TEL;就在网上找了一个时间复杂度为O(nlogn)的算法,其算法思想为:(网上找的)

    假设要寻找最长上升子序列的序列是a[n],然后寻找到的递增子序列放入到数组b中。

    (1)当遍历到数组a的第一个元素的时候,就将这个元素放入到b数组中,以后遍历到的元素都和已经放入到b数组中的元素进行比较;

    (2)如果比b数组中的每个元素都大,则将该元素插入到b数组的最后一个元素,并且b数组的长度要加1;

    (3)如果比b数组中最后一个元素小,就要运用二分法进行查找,查找出第一个比该元素大的最小的元素,然后将其替换。

    在这个过程中,只重复执行这两步就可以了,最后b数组的长度就是最长的上升子序列长度。例如:如该数列为:

    5 9 4 1 3 7 6 7

    那么:

    5 //加入
    5 9 //加入
    4 9 //用4代替了5
    1 9 //用1代替4
    1 3 //用3代替9
    1 3 7 //加入
    1 3 6 //用6代替7
    1 3 6 7 //加入

    最后b中元素的个数就是最长递增子序列的大小,即4。

    要注意的是最后数组里的元素并不就一定是所求的序列,

    例如如果输入 2 5 1

    那么最后得到的数组应该是 1 5

    而实际上要求的序列是 2 5

    代码如下:

    #include<stdio.h>
    const int MAXN=500010;
    int a[MAXN],b[MAXN];

    //用二分查找的方法找到一个位置,使得num>b[i-1] 并且num<b[i],并用num代替b[i]
    int Search(int num,int low,int high)
    {
    int mid;
    while(low<=high)
    {
    mid=(low+high)/2;
    if(num>=b[mid]) low=mid+1;
    else high=mid-1;
    }
    return low;
    }
    int DP(int n)
    {
    int i,len,pos;
    b[1]=a[1];
    len=1;
    for(i=2;i<=n;i++)
    {
    if(a[i]>=b[len])//如果a[i]比b[]数组中最大还大直接插入到后面即可
    {
    len=len+1;
    b[len]=a[i];
    }
    else//用二分的方法在b[]数组中找出第一个比a[i]大的位置并且让a[i]替代这个位置
    {
    pos=Search(a[i],1,len);
    b[pos]=a[i];
    }
    }
    return len;
    }
    int main()
    {

    int n;
    int iCase=0;
    int i,j;
    int x,y;
    while(scanf("%d",&n)!=EOF)
    {
    iCase++;
    for(i=1;i<=n;i++)
    {
    scanf("%d%d",&x,&y);
    a[x]=y;
    }
    int res=DP(n);
    printf("Case %d:\n",iCase);
    if(res==1)
    {
    printf("My king, at most 1 road can be built.\n\n");
    }
    else
    printf("My king, at most %d roads can be built.\n\n",res);
    }
    return 0;
    }
  • 相关阅读:
    去除字符串重复数据 分类: python基础学习 2013-08-08 17:43 171人阅读 评论(0) 收藏
    python中计时工具timeit模块的基本用法 分类: python python基础学习 2013-08-08 10:05 2072人阅读 评论(0) 收藏
    socket通信简介 分类: socket 2013-08-06 17:49 209人阅读 评论(0) 收藏
    AF_INET和PF_INET的细微不同 分类: socket 2013-08-06 17:35 264人阅读 评论(0) 收藏
    查看linux操作系统版本号 分类: ubuntu 2013-08-05 10:14 265人阅读 评论(0) 收藏
    python yield生成器 分类: python基础学习 2013-08-04 15:40 324人阅读 评论(0) 收藏
    html 元素 2013-08-04 14:53 236人阅读 评论(0) 收藏
    UTF8默认编码下的MYSQL命令框中输入汉字显示乱码的问题 分类: 测试 2013-08-02 14:16 371人阅读 评论(0) 收藏
    os.path模块学习 2013-07-30 17:46 193人阅读 评论(0) 收藏
    python 操作windows下的目录 分类: python python基础学习 2013-07-30 17:30 274人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/kuangbin/p/2412725.html
Copyright © 2011-2022 走看看