HDU1025 Constructing Roads In JGShining's Kingdom

最长上升子序列

题目大意:有两列城市,每列n个,一部分为rich,另一部分为poor,编号分别是自左向右为1到n,然后poor列的城市向rich出口资源,要求是每一个poor城市只能且必须向一个rich城市出口资源,出口资源需要建设道路,且道路不能有交叉,问最多建设几条道路。

在纸上画一下就会发现,我们把poor列的城市按升序排列,其对应的出口城市(rich城市)就会有一个新的序列,在这个序列中,只要rich城市编号比前一个城市的编号大,那么就可以在该城市和其对应的poor城市之间建设一条不会和前面道路相交的道路,那么就把问题转换成了最长上升子序列问题了,要注意的是本题数据量比较大,用O(n^2)算法的话会超时,改用O(nlogn)算法。

#include <cstdio>
#include <iostream>
#include <algorithm>
#define MAX 500005
using namespace std;
typedef struct A
{
    int p,r;
}City;
City city[MAX];
int stack[MAX];
int cmp(const A &a,const A &b)
{
    return a.p<b.p;
}
int LIS(int temp,int len)
{
    int left=1,right=len;
    int mid;
    while(left<=right)
    {
        mid=(left+right)/2;
        if(temp>stack[mid])  left=mid+1;
        else right=mid-1;
    }
    return left;
}
int main()
{
    int n,len,Q=0,p,r;
    while(scanf("%d",&n)!=-1)
    {
        Q++;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&city[i].p,&city[i].r);
        }
        sort(city+1,city+1+n,cmp);
        len=1;
        stack[len]=city[1].r;
        for(int i=1;i<=n;i++)
        {
            if(city[i].r>stack[len])
              stack[++len]=city[i].r;
            else
            {
                int j=LIS(city[i].r,len);
                stack[j]=city[i].r;
            }
        }
        if(len==1) printf("Case %d:\nMy king, at most %d road can be built.\n\n",Q,len);
        else printf("Case %d:\nMy king, at most %d roads can be built.\n\n",Q,len);
    }
    return 0;
}



改进后的程序:

(不用创建结构体,之间用city[p]=r来表示两者之间一一对应的关系即可)

#include <cstdio>

#include <iostream>
#include <algorithm>
#define MAX 500005
using namespace std;
int ans[MAX];
int stack[MAX];
int LIS(int temp,int len)
{
    int left=1,right=len;
    int mid;
    while(left<=right)
    {
        mid=(left+right)/2;
        if(temp>stack[mid])  left=mid+1;
        else right=mid-1;
    }
    return left;
}
int main()
{
    int n,len,Q=0,p,r;
    while(scanf("%d",&n)!=-1)
    {
        Q++;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&p,&r);
            ans[p]=r;
        }
        len=1;
        stack[len]=ans[1];
        for(int i=1;i<=n;i++)
        {
            if(ans[i]>stack[len])
              stack[++len]=ans[i];
            else
            {
                int j=LIS(ans[i],len);
                stack[j]=ans[i];
            }
        }
        if(len==1) printf("Case %d:\nMy king, at most %d road can be built.\n\n",Q,len);
        else printf("Case %d:\nMy king, at most %d roads can be built.\n\n",Q,len);
    }
    return 0;
}

你可能感兴趣的:(HDU1025 Constructing Roads In JGShining's Kingdom)