宇宙旅行
题意:
在一个外向基环树森林里求最长上升子序列。
此处的子序列是指在一条路径上。
n <= 100000
解:
硬是想不出来......
回忆一般的最长单增子序列做法,我们有个f[]数组表示的是i长度的最小结尾。
那放到树上怎么搞呢?
我们可以DFS,然后发现每到一个点,f数组只会变动一位,于是我们可以记录下来,回溯的时候消除影响。
然后就是一大堆毒瘤的细节处理.....
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 5 const int N = 100010, INF = 0x7f7f7f7f; 6 7 struct Edge { 8 int nex, v; 9 }edge[N << 1]; int top; 10 11 int e[N], val[N], to[N], stk[N], t, f[N], c, gt[N], ans = 1; 12 bool in_stk[N], vis[N]; 13 14 inline void add(int x, int y) { 15 top++; 16 edge[top].nex = e[x]; 17 edge[top].v = y; 18 e[x] = top; 19 return; 20 } 21 22 inline void DFS_1(int x) { 23 if(in_stk[x]) { 24 c = x; 25 return; 26 } 27 if(vis[x]) { 28 return; 29 } 30 in_stk[x] = 1; 31 stk[++t] = x; 32 vis[x] = 1; 33 DFS_1(gt[x]); 34 t--; 35 in_stk[x] = 0; 36 return; 37 } 38 39 void DFS(int x) { 40 int l = 0, r = top; 41 while(l < r) { 42 int mid = (l + r + 1) >> 1; 43 if(f[mid] < val[x]) { 44 l = mid; 45 } 46 else { 47 r = mid - 1; 48 } 49 } 50 r++; 51 int t_top = top; 52 int t_r = f[r]; 53 if(r > top) { 54 top = r; 55 f[r] = val[x]; 56 } 57 ans = std::max(ans, r); 58 if(val[x] < f[r]) { 59 f[r] = val[x]; 60 } 61 for(int i = e[x]; i; i = edge[i].nex) { 62 int y = edge[i].v; 63 DFS(y); 64 } 65 top = t_top; 66 f[r] = t_r; 67 return; 68 } 69 70 inline void solve() { 71 int x = c; 72 top = 0; 73 do { 74 f[++top] = val[x]; 75 x = gt[x]; 76 }while(x != c); 77 std::sort(f + 1, f + top + 1); 78 top = std::unique(f + 1, f + top + 1) - f - 1; 79 ans = std::max(ans, top); 80 x = c; 81 int y = x; 82 do { 83 y = x; 84 x = gt[x]; 85 for(int i = e[x]; i; i = edge[i].nex) { 86 int z = edge[i].v; 87 if(z != y) { 88 DFS(z); 89 } 90 } 91 }while(x != c); 92 memset(f + 1, 0, top * sizeof(int)); 93 return; 94 } 95 96 int main() { 97 int n; 98 val[0] = INF; 99 scanf("%d", &n); 100 for(int i = 1; i <= n; i++) { 101 scanf("%d", &val[i]); 102 } 103 for(int i = 1, x; i <= n; i++) { 104 scanf("%d", &x); 105 add(x, i); 106 gt[i] = x; 107 } 108 109 int tc = -1; 110 for(int i = 1; i <= n; i++) { 111 if(!vis[i]) { 112 DFS_1(i); 113 if(c != tc) { 114 solve(); 115 tc = c; 116 } 117 } 118 } 119 printf("%d", ans); 120 return 0; 121 }