题目链接: 点击打开链接
题目大意: 有n对国家,每对国家一个缺资源,一个有资源。穷的国家按序号从左到右排列,富的国家也一样。要在一穷,一富国家之间建立一条铁路,而且铁路不能交叉,问最多能建多少铁路。
思路: LIS
分析:
将每条铁路按富国家序号从小到大排列,要使铁路不交叉,另一端的穷国家得排成一个上升序列。只要中间有一个穷国家不满足递增关系,那么铁路就会出现交叉。其实就是最长上升子序列问题。数据量有点大,用NlogN复杂度的方法做。
代码:
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 500000 + 10;
struct city_pair {
int r, p;
} pairs[maxn];
int n, LIS[maxn];
bool comp(const city_pair& p1, const city_pair& p2)
{
return p1.r < p2.r;
}
int binary_search(int start, int end, int target)
{
while (end > start) {
int mid = (end + start) / 2;
if (target > LIS[mid])
start = mid + 1;
else
end = mid;
}
return start;
}
int lis()
{
LIS[1] = pairs[1].p;
int maxl = 1;
for (int i = 2; i <= n; ++i) {
if (pairs[i].p > LIS[maxl])
LIS[++maxl] = pairs[i].p;
else {
int pos = binary_search(1, maxl, pairs[i].p);
LIS[pos] = pairs[i].p;
}
}
return maxl;
}
int main()
{
int kase = 1;
while (scanf("%d", &n) == 1) {
for (int i = 1; i <= n; ++i)
scanf("%d %d", &pairs[i].p, &pairs[i].r);
sort(pairs + 1, pairs + n + 1, comp);
int ans = lis();
if (ans == 1)
printf("Case %d:\nMy king, at most %d road can be built.\n\n", kase++, lis());
else
printf("Case %d:\nMy king, at most %d roads can be built.\n\n", kase++, lis());
}
}