您的位置:首页 > 其它

hdu 1025 Constructing Roads In JGShining's Kingdom

2016-05-02 15:24 239 查看

题目大意

题目挺长的,有点不容易读懂,意思就是给你2n个城市,一班为poor city,一半为rich city,每一个poor city需要对应的rich city提供相对应缺少的资源。这样一一对应,因为要建道路,并且要建足够多的道路,同时道路之间不能有相交情况。

题目分析

因为每一个poor city的编号为1~n,每一个下标对应一个rich city,需要修建足够多的道路并且道路不想交,转化一下大家会发现,就是求以poor city的编号为数组本身下标的最长递增子序列长度。需要注意的是,求最长递增子序列长度的朴素算法时间复杂度为(n*n),当n达到40000的时候就会TLE,因此这里我们需要2分查找使时间复杂度为O(n*log n)。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn = 500005;
int a[maxn],g[maxn],dp[maxn];

int main()
{
int n,kase = 0;
while(scanf("%d", &n) != EOF)
{
int x,y;
for(int i = 1; i <= n; i++) //因为下标必定为1~n并且不会重复,所以直接这样写就不用写结构体并且sort.
{
scanf("%d %d", &x, &y);
a[x] = y;
}
for(int i = 1; i < maxn; i++)
g[i] = maxn;
for(int i = 1; i <= n; i++)
{
int k = lower_bound(g+1, g+n+1, a[i]) - g; //lower_bound()用于查找大于或者等于a[i]的g数组的地址
dp[i] = k;
g[k] = a[i]; //更新g[k]的值
}
int ans = 0;
for(int i = 1; i <= n; i++)  //找到最长的递增子序列长度
ans = max(ans, dp[i]);
if(ans == 1)   //输出有坑,注意只有一条道路是,road后面不加s,并且输出之后要添加空行
printf("Case %d:\nMy king, at most %d road can be built.\n\n", ++kase, ans);
else
printf("Case %d:\nMy king, at most %d roads can be built.\n\n", ++kase, ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: