zoukankan      html  css  js  c++  java
  • Constructing Roads In JGShining's Kingdom_最长上升子序列

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
    Total Submission(s) : 64   Accepted Submission(s) : 21

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    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.

    从poor city和rich city之间修路,不能交叉,问最多能修几条。

    rich city从左到右增大,即求最大上升子序列。

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

    (1)把mp中第一个元素放入b,lenb++;

    (2)取第二个元素如果比b数组中的每个元素都大,则将该元素插入到b数组的最后一个元素,lenb加1;

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

    重复2,3.最后返回lenb就是最长上升子序列长度。例如:如该数列为:

    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<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    const int N=500010;
    int mp[N],b[N];
    int findy(int num,int left,int right)
    {
        int mid;
        while(left<=right)
        {
            mid=(left+right)/2;
            if(num>=b[mid]) left=mid+1;
            else right=mid-1;
        }
        return left;
    }
    int dp(int n)
    {
        int i,len,pos;
        b[1]=mp[1];
        len=1;
        for(i=2;i<=n;i++)
        {
            if(mp[i]>=b[len])
            {
                len=len+1;
                b[len]=mp[i];
            }
            else //用二分的方法在b[]数组中找出第一个比mp[i]大的位置并且让mp[i]替代这个位置
            {
                pos=findy(mp[i],1,len);
                b[pos]=mp[i];
            }
        }
        return len;
    
    }
    int main()
    {
        int n;
        int cas=0;
        while(~scanf("%d",&n))
        {
    
            int a,b;
            cas++;
            for(int i=1;i<=n;i++)
            {
                scanf("%d%d",&a,&b);
                mp[a]=b;
            }
            int ans=dp(n);
    
            printf("Case %d:
    ",cas);
            if(ans==1)//ans是1的时候road不用加s,刚开始也没注意...
                printf("My king, at most %d road can be built.
    
    ",ans);
            else
            printf("My king, at most %d roads can be built.
    
    ",ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    verilog之计数器0~9999——数码管显示
    C语言的谜题
    modelsim SE6.2b的常用问题
    [转载]MDK常见报错(编译arm)
    Nios II之LED实验(SDRAM+EPCS4配置)————基于Altera的DE0开发板
    poj2210
    poj1161
    poj1555
    poj2337
    poj1107
  • 原文地址:https://www.cnblogs.com/iwantstrong/p/5741307.html
Copyright © 2011-2022 走看看