ASC(1)--G(DP,双LIS)
2014-11-09 17:22:51
思路:这题简而言之就是给你N个数对,每个数对有两个数s和b,让你求最长的使得s和b都严格上升的数列。
首先将s升序排序,s相同的情况将b降序排序,这样就是直接在剩下的b数列中求LIS了(因为s升,b降这样排的话不会使最后的序列里b对应的s相等,思考)
1 /************************************************************************* 2 > File Name: b.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Sun 09 Nov 2014 05:04:05 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 27 int N; 28 int que[100010],len; 29 int path[100010]; 30 int pre[100010]; 31 32 struct node{ 33 int s,b,id; 34 }t[100010]; 35 36 bool cmp(node a,node b){ 37 if(a.s == b.s) 38 return a.b > b.b; 39 return a.s < b.s; 40 } 41 42 int B_search(int val){ 43 int l = 1,r = len + 1; 44 while(l < r){ 45 int mid = getmid(l,r); 46 if(que[mid] >= val) 47 r = mid; 48 else 49 l = mid + 1; 50 } 51 return l; 52 } 53 54 void Print(int p){ 55 if(pre[p] != -1) 56 Print(pre[p]); 57 if(pre[p] != -1) printf(" "); 58 printf("%d",p); 59 } 60 61 int main(){ 62 scanf("%d",&N); 63 for(int i = 1; i <= N; ++i){ 64 scanf("%d%d",&t[i].s,&t[i].b); 65 t[i].id = i; 66 } 67 sort(t + 1,t + N + 1,cmp); 68 path[0] = -1; 69 for(int i = 1; i <= N; ++i){ 70 int pos = B_search(t[i].b); 71 if(que[pos] == t[i].b) 72 continue; 73 que[pos] = t[i].b; 74 path[pos] = t[i].id; 75 pre[t[i].id] = path[pos - 1]; 76 if(pos > len) 77 ++len; 78 } 79 printf("%d\n",len); 80 Print(path[len]); 81 printf("\n"); 82 return 0; 83 }