HDUOJ 1025

来源:互联网 发布:编译c 的软件 编辑:程序博客网 时间:2024/06/10 08:56

原题

  • Problem Description

    …….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.

  • 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.

解题思路:

  • 注意输出格式!!!road和roads!!!
  • 说实话这道题的题我读了好久好久,题意理解的(好久×10000)【网上的题意解读杂七杂八很难懂,崩溃ing】,这道题应该这么理解,才能懂应该怎么去解题:
    • 输入一个数n表示poor和rich各有n座城市
    • 每一行输入两个数字x、y,分别表示坐标为 x 的poor城市想要坐标为 y 的rich城市的资源
    • poor和rich的所有城市的坐标都是从左到右依次递增的,即两个城市的各个坐标从左到右为1,2,3,……..,n
    • 然后再对应把两个相互需求的p和r城市连接起来,不能有交叉,算出最多能连几条线,即能修多少条路
    • 举个经典的例子:
      • 5
      • p:2 3 4 1 5
      • c:2 3 1 4 5
      • 如果在坐标上进行连线,很容易可以看出最多可以连3条线(22,33,55)
      • p:1 2 3 4 5
      •       | |   |
      • c:1 2 3 4 5
      • 1和4,4和1相连都会有交叉
  • 所以这个时候应该就有思路了,可以这么去解题:用一个数组a[n]来存每个p城市的坐标对应的c城市的坐标,a[i] = value : i表示p的坐标,value表示c的坐标,这样p城市的坐标就相当于已经排序好了,现在只需要求出数组a的最长递增子序列,这样肯定能保证求出来的结果不会交叉(p是排好序的,即数组a的下标),而且是最好的结果。

代码:

最长递增子序列优化算法:O(nlogn)

#include <stdio.h>#include <iostream>using namespace std;int dp[500001], temp[500001];int BinarySearch(int tail, int findValue)//二分查找{    int head = 1;    int mid = (head + tail) / 2;    while (mid != 1 && mid != tail)    {        if (dp[mid] == findValue)return mid;        if (dp[mid] > findValue)            tail = mid;        else            head = mid;        mid = (head + tail) / 2;        if (head + 1 == tail && dp[mid] < findValue)            return mid + 1;    }    if (mid == 1 && dp[mid] > findValue)return 1;    else return 2;}int main(){    int temp_p, temp_r, i, dpIndex;    int n, Case = 0;    while (scanf("%d", &n) != EOF)    {        Case++;        for (i = 1; i <= n; i++)        {            scanf("%d%d", &temp_p, &temp_r);            temp[temp_p] = temp_r;        }        dp[1] = temp[1];        dpIndex = 1;        for(i = 2; i <= n; i++)        {            if (temp[i] > dp[dpIndex])                dp[++dpIndex] = temp[i];            else                dp[BinarySearch(dpIndex, temp[i])] = temp[i];        }        if(dpIndex == 1)        {            printf("Case %d:\n", Case);            printf("My king, at most 1 road can be built.\n\n");        }else        {            printf("Case %d:\n", Case);            printf("My king, at most %d roads can be built.\n\n", dpIndex);        }    }}
原创粉丝点击