标签:style blog io ar color os sp for on
首先根据第一个数排序,然后可以得到一串第二个数组成的序列,因为第一个由大到小排列,所以第二组中取到的数据,后面的不能比前面的小才不会形成交叉,那么也就是求这个新序列的最长公共子序列
这里要用到最长上升子序列的nlogn的算法,新建一个数组保存所有合理的数据的数组g,比如g数组中有了1,4,6,加进来一个3 , 那么4可以被3代替因为在同一个位置尽可能小能容纳的数据个数就会越多,越能找到更长的序列,这个找位置的过程就用二分搜索logn的复杂度
注意一点,我是因为这个好久没做出。。。。就是边数大于1的时候road会变为复数roads
另外这是看的别人的直接写在main函数中的二分,觉得比我的简便很多
ans[1]=num[1];
len=1;
for(i=2;i<=n;i++)
{
/*****/ //这个二分是别人写的,表示比我写的好多了- -I。
low=1;
up=len;
while(low<=up)
{
mid=(low+up)/2;
if(ans[mid]<num[i]) low=mid+1;
else up=mid-1;
}
ans[low]=num[i];
if(low>len) len++;
/*****/
}
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 using namespace std; 6 7 const int maxn = 500005; 8 int num[maxn] , g[maxn]; //g数组存一个顺序序列 9 10 struct Pair{ 11 int x , y; 12 bool operator<(const Pair &m)const{ 13 return x < m.x; 14 } 15 }p[maxn]; 16 17 int bin_search(int m , int k) 18 { 19 int st = 0 , la = k , ans = 0; 20 int mid; 21 while(st <= la){ 22 mid = (st + la) / 2; 23 if( m > g[mid] && m <= g[mid + 1]){ 24 ans = mid + 1; 25 break; 26 } 27 else if(m <= g[mid]) la = mid - 1; 28 else st = mid + 1; 29 } 30 return ans; 31 } 32 33 int main() 34 { 35 // freopen("a.in" , "r" , stdin); 36 int n , cas = 0; 37 while(scanf("%d" , &n) != EOF){ 38 for(int i = 0 ; i<n ; i++){ 39 scanf("%d%d" , &p[i].x , &p[i].y); 40 } 41 sort(p , p+n); 42 43 for(int i = 0 ; i<n ; i++) 44 num[i+1] = p[i].y; 45 46 int k = 0; 47 g[0] = 0; 48 for(int i = 1 ; i<=n ; i++){ 49 if(num[i] > g[k]) g[++k] = num[i]; 50 else{ 51 int pos = bin_search(num[i] , k); 52 g[pos] = num[i]; 53 } 54 } 55 //这里不止一条路的话是复数roads!!! 56 if(k == 1) printf("Case %d:\nMy king, at most %d road can be built.\n" , ++cas , k); 57 else printf("Case %d:\nMy king, at most %d roads can be built.\n" , ++cas , k); 58 puts(""); 59 } 60 return 0; 61 }
标签:style blog io ar color os sp for on
原文地址:http://www.cnblogs.com/CSU3901130321/p/4166148.html