宇宙旅行

题意:

在一个外向基环树森林里求最长上升子序列。

此处的子序列是指在一条路径上。

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 }
AC代码

 

posted @ 2018-09-29 20:03  huyufeifei  阅读(264)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜