hdu 1025 Constructing Roads In JGShining's Kingdom

来源:互联网 发布:户型图设计软件 编辑:程序博客网 时间:2024/05/09 14:19

题目大意

题目挺长的,有点不容易读懂,意思就是给你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;}
1 0
原创粉丝点击