hdu1025 最长上升子序列

来源:互联网 发布:四万亿计划后果 知乎 编辑:程序博客网 时间:2024/05/21 19:05

题目大意:2n个村庄,n个富有,n个贫穷,贫穷的需要从富有村庄进口东西,也就是说需要建一条路,一直编号都是从1……n,问最多可以减多少条路,满足贫穷村庄编号大的则相连的富有的编号也大。


思路:最长上升子序列问题。g[i]表示序列长度为i的最小村庄编号,dp[i]表示第i个村庄为最后一个村庄时总共有多少条路。每次从g中找到小于arr[i]的位置,及加入arr[i]后dp[i]的值,并更新g[i] , 最后求最大的dp值即可

ps:输出时因为1和大于1的不一样, road变为roads,,,,,,细节决定成败!!


#include <cstdio>#include <string>#include <cstring>#include <fstream>#include <algorithm>#include <cmath>#include <queue>#include <stack>#include <vector>#include <map>#include <set>#include <iostream>#include <iomanip>using namespace std;#define maxn 1000005#define MOD 1000000007#define mem(a) memset(a , 0 , sizeof(a))#define LL __int64#define INF 999999999int n ;int dp[maxn];int g[maxn];int arr[maxn];int Find(int a,int l,int r){    int mid=(l+r)/2;    while (l<=r)    {        if (a==g[mid]) return mid;        else        {            if (a>g[mid]) l=mid+1;            else r=mid-1;            mid=(l+r)/2;        }    }    return l;}int main(){    int n;    int k = 0;    while(scanf("%d" , &n) != EOF)    {        int x , y;        for(int i = 0 ; i < n ; i ++)        {            scanf("%d %d" , &x , &y);            arr[x] = y;        }        for(int i = 0 ; i <= n ; i ++) g[i] = INF;        mem(dp);        for(int i = 1 ; i <= n ; i ++)        {            int k = lower_bound(g + 1 , g + n + 1, arr[i]) - g;          //  int k = Find(arr[i] , 1 , n);            dp[i] = k ;            g[k] = arr[i];        }        int ans = 0;        for(int i = 1 ; i <= n ; i ++)            if(ans < dp[i]) ans = dp[i];        if(ans == 1) printf("Case %d:\nMy king, at most %d road can be built.\n\n" , ++k , ans);        else printf("Case %d:\nMy king, at most %d roads can be built.\n\n" , ++k , ans);    }    return 0;}


0 0
原创粉丝点击