#原题:
- 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);
}
}
}