hdoj1025 Constructing Roads In JGShining's Kingdom (最长递增子序列 , map)

来源:互联网 发布:java优先级队列 编辑:程序博客网 时间:2024/05/17 22:41

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1025

题意:

有a,b两组数,每组有n个数字,分别是1,2,3,...,n,(1<=n<=500000);两组数各自做特定的乱序排列,分n次输入这两组排列数,每次输入各组一个数(如ai ,bi),每次输入的这两个数是绑定在一起的,现在将a组的数升序排序,此时b组的数字会有相应的位置变化(如原来a:1324,b:2431;排序后a:1234,b:2341);求b组现在的最大上升子序列中数字的个数。

思路:

用map<int,int>city来存入数据,则有city[a]=b,这样a是自动升序存放的,只需要求出b的最大上升子序列即可;minvalue[i]表示前j个数中最长上升子序列数字个数为i的所有结果中最后一个数最小的那个值,如前6个数(1,2,5,6,3,4)中最长上升子序列为4的结果有两组织,分别为1,2,5,6和1,2,3,4,那么minvalue[4]=4,表示前6个数中,最长上升子序列数字个数为4时,尾数最小的值是4;当j变大时,对于每一个特定的i值,这个minvalue[i]都需要实时更新,而且minvalue[]中的值肯定是递增存放的,所以可以二分查找;这里我们顺序搜索b组数字,每个数字都到minvalue[]里面去匹配找到自己所能组成的最长上升子序列个数,如minvalue[5]=10,minvalue[6]=18,当你现在正用数字14在匹配,那么它能组成的最长上升子序列数字个数一定为6,而且此时它要更新minvalue[6]=14。最终最大的i值即是我们要的最大上升子序列的个数。

#include <iostream>#include <stdio.h>#include <map>using namespace std;int minvalue[500002]={0};int ans;int longsub(int begin,int end,int value){int mid;while(begin<=end){mid=(begin+end)/2;if(value>minvalue[mid])begin=mid+1;elseend=mid-1;}minvalue[begin]=value;if(begin>ans)ans=begin;return 0;}int main(){int cas,n,p,r,i;map<int,int>city;cas=0;while(scanf("%d",&n)!=EOF){cas++;for(i=1;i<=n;i++){scanf("%d %d",&p,&r);city[p]=r;}ans=0;for(i=1;i<=n;i++){longsub(1,ans,city[i]);}printf("Case %d:\n",cas);if(ans==0||ans==1)printf("My king, at most %d road can be built.\n\n",ans);else printf("My king, at most %d roads can be built.\n\n",ans);}return 0;}


阅读全文
0 0
原创粉丝点击