最长上升子序列NLOGN算法
来源:互联网 发布:热血无赖优化 编辑:程序博客网 时间:2024/05/22 04:48
http://boj.me/onlinejudge/showproblem.php?problem_id=1836
Description
Comic Board是个神奇的地方,宽阔的AC河笔直地穿过这片土地。Comic
Board有N个国家(编号从1至N),每个国家在河两岸各有7座城池,象征着七色的彩虹。城市沿着河岸一字排开,构成了一幅美丽而壮阔的山水长卷。
现在Comic Board的众国家准备联合在河上建彩虹桥,以便游客能更好地欣赏AC河。由于跨国建桥将涉及到国境线与护照等问题,因此他们只打算在两岸相同国家的城市间建桥。为了发展旅游业,他们希望建尽量多的桥来吸引游客。现在,他们把任务交给了Chirlley国的首席工程师车裂。你能帮她算出最多能建多少座彩虹桥吗?
Input
多组数据。
第一行为正整数T(0 < T < 10),表示有T组数据。
对于每组数据:
第一行为一个整数N(0 < N <= 10000),表示有N个国家。
第二行,第三行为7N个从1至N的整数,分别表示两岸的城市所属的国家。
Output
对于每组数据,输出一行,即最多能建造的彩虹桥的数目。
Sample Input
2
2
1 2 2 2 2 1 2 1 2 1 2 1 1 1
2 1 2 1 2 2 2 1 1 2 1 1 2 1
3
3 1 1 3 1 3 3 1 2 2 1 2 1 1 2 2 2 3 3 3 2
1 3 3 1 1 3 3 1 1 2 3 3 3 1 1 2 2 2 2 2 2
Sample Output
11
14
#include <iostream>#include <vector>#include <algorithm>using namespace std;typedef int(*Array8)[8];Array8 p[700001];int T;int N;int len[100001];int f[100001][8];int bsearch(int low,int high,int key){ while(low <= high) { int mid = (low+high)/2; if(len[mid] > key) high = mid -1; else if(len[mid] < key) low = mid +1; else return mid; } return high;}int DP(){ int top =1; memset(len,7*N+1,(7*N+1)*sizeof(int)); len[0] = 0; len[1] = (*p[1])[7]; int max = -1; for(int i=1;i<=7*N;i++) //nlogn算法 { for(int j=7;j>=1;j--) { if((*p[i])[j] > len[top]) { top++; len[top] = (*p[i])[j]; if(max < top) max = top; } else if((*p[i])[j] < len[top]) { int xiabiao = bsearch(1,top,(*p[i])[j]); if(len[xiabiao] != (*p[i])[j]&& len[xiabiao+1] >(*p[i])[j]) { len[xiabiao+1] = (*p[i])[j]; if(max < xiabiao+1) max = xiabiao+1; } } else continue; } } return max;}int main(){ cin>>T; while(T--) { scanf("%d",&N); int temp; memset(f,0,sizeof(f)); for(int i=1;i<=7*N;i++) { scanf("%d",&temp); for(int j=1;j<=7;j++) if(f[temp][j]==0) { f[temp][j] = i; // 桥,下面国家对上面国家 break; } } for(int i=1;i<=7*N;i++) { scanf("%d",&temp); p[i] = &f[temp]; } cout<<DP()<<endl; } return 0; }
#include <iostream> using namespace std;const int MinValue = -9999999;//在上升的序列array[]找到最大的i,使得 array[i]<=key ,//找到返回这个i,找不到返回0,s=1,从1开始 int bisearch(int s,int e,int key,int * array){ if(s > e) return -1; while(s < e -1) { int mid = s +(e-s)/2; if(key <= array[mid]) //使整个 区间 往 左移 e = mid ; else s = mid ; } if(array[e] <= key ) return e; else if(array[s]<= key) return s; else return 0; }int LIS(int* array ,int N){ //单调递增 序列 int* len_min = new int[N+1];// 长度为i的 最长上升子序列中,结尾数字 的最小值 memset(len_min,0,(N+1)*sizeof(int)); len_min[1] = array[0]; len_min[0] = MinValue; //设置长度为0时,结尾数字为最小 int len = 1;//len_min数组的长度, //也是以 i 结尾的序列中,最长上升子序列的长度的最大值 for(int i=1;i<N;i++) { //找到 比array[i]小的 最大的数的下标, 返回至少为0 int xiaBiao =bisearch(1,len,array[i],len_min); //目前最长的上升子序列 if(len_min[xiaBiao+1]==0) { len++; } //更新 长度为 xiaBiao+1的上升序列的,结尾数字的最小值 len_min[xiaBiao+1] = array[i]; } for(int i=0;i<N+1;i++) cout<<len_min[i]<<" "; cout<<endl; delete []len_min; len_min = 0; return len; }int main(){ int array[] = {1,9,2,10,6,7,3,4,5,8}; int N = sizeof(array)/sizeof(int); int cnt = LIS(array , N); cout<<cnt<<endl; system("pause"); return 0;}
- 最长上升子序列nlogn算法
- 最长上升子序列nlogn算法
- 最长上升子序列NLOGN算法
- 最长上升子序列O(nlogn)算法
- 最长上升子序列----nlogn算法-模板
- bsoj2234 最长上升子序列nlogn算法
- 最长上升子序列nlogn算法
- 最长上升子序列nlogn算法
- 最长上升子序列nlogn算法
- 最长上升子序列nlogn算法
- 最长上升子序列nlogn算法
- 最长上升子序列nlogn算法
- 最长上升子序列nlogn算法
- 最长上升子序列nlogn算法
- 最长上升子序列nlogn算法
- 最长上升子序列O(nlogn)算法
- 最长上升子序列O(NlogN)算法
- 最长上升子序列nlogn算法
- c文件操作
- 2011.07.26
- Android上dip、dp、px、sp等单位说明
- JBPM之流程定义基本概念(通过请假流程进行解释)
- 关于“做一个聊天+信息分享客户端”的设想(SNS?)
- 最长上升子序列NLOGN算法
- Meta标签的使用(搜索方面)
- PCI总线和PCIE总线的差异
- Session Manager
- delphi中利用winsock判断是否ping通某IP
- MD5加密密码
- Netstat命令详解 和服务启动批处理
- [转帖] 关于ET 测试方法研究
- 装饰模式