• 小R的树(权限题)


    解:考场上爆0了......

    回想怎么求两个排列的最长公共子序列。

    回想怎么求1~n每个数恰出现两次的两个序列的最长公共子序列。就是每个数替换为它在另一个序列里的出现位置,降序。

    所以我们可以把这每个空位都倒序填入m个数,然后暴力,最后输出方案。

    考虑优化。发现在每个空位的时候,这m个数都是单降的。直接拿指针在单调栈上扫,可以O(top + m)转移。

    关于记录方案,每个位置记录以它结尾的lis中的前一个非-1位置,以及在这之间有多少个-1。

    然后就可以把空间优化到O(n)。

     1 #include <bits/stdc++.h>
     2 
     3 typedef long long LL;
     4 const int N = 200010;
     5 const LL INF = 0x3f3f3f3f3f3f3f3fll;;
     6 
     7 struct Node {
     8     int a, b;
     9     Node(int A = 0, int B = 0) {
    10         a = A;
    11         b = B;
    12     }
    13 }frp[N], fr[N];
    14 
    15 LL a[N], b[N], p[N];
    16 int top, n, m;
    17 bool vis[N];
    18 
    19 int main() {
    20     scanf("%d", &n);
    21     for(int i = 1; i <= n; i++) {
    22         scanf("%lld", &a[i]);
    23     }
    24     scanf("%d", &m);
    25     for(int i = 1; i <= m; i++) {
    26         scanf("%lld", &b[i]);
    27     }
    28     std::sort(b + 1, b + m + 1);
    29     std::reverse(b + 1, b + m + 1);
    30     a[n + 1] = INF;
    31     for(int i = 1; i <= n + 1; i++) {
    32         if(a[i] != -1) {
    33             int l = 0, r = top;
    34             while(l < r) {
    35                 int mid = (l + r + 1) >> 1;
    36                 if(p[mid] < a[i]) l = mid;
    37                 else r = mid - 1;
    38             }
    39             fr[i] = frp[r];
    40             if(r == top) {
    41                 p[++top] = a[i];
    42                 frp[top] = Node(i, 0);
    43             }
    44             else if(p[r + 1] > a[i]) {
    45                 p[r + 1] = a[i];
    46                 frp[r + 1] = Node(i, 0);
    47             }
    48         }
    49         else {
    50             int p1 = top;
    51             for(int j = 1; j <= m; j++) {
    52                 while(p1 && p[p1] >= b[j]) {
    53                     p1--;
    54                 }
    55                 Node temp = frp[p1];
    56                 temp.b++;
    57                 if(p1 == top) {
    58                     p[++top] = b[j];
    59                     frp[top] = temp;
    60                 }
    61                 else if(p[p1 + 1] > b[j]) {
    62                     p[p1 + 1] = b[j];
    63                     frp[p1 + 1] = temp;
    64                 }
    65             }
    66         }
    67     }
    68 
    69     int now = frp[top].a, p1 = n, p2 = 1;
    70     while(now) {
    71         if(fr[now].b) {
    72             while(p1 > now) p1--;
    73             while(b[p2] >= a[now]) p2++;
    74             for(int i = 1; i <= fr[now].b; i++) {
    75                 while(a[p1] != -1) p1--;
    76                 a[p1] = b[p2];
    77                 vis[p2] = 1;
    78                 p2++;
    79             }
    80         }
    81         now = fr[now].a;
    82     }
    83 
    84     p2 = 1;
    85     for(int i = 1; i <= n; i++) {
    86         if(a[i] == -1) {
    87             while(vis[p2]) p2++;
    88             a[i] = b[p2];
    89             p2++;
    90         }
    91     }
    92 
    93     for(int i = 1; i <= n; i++) {
    94         printf("%lld ", a[i]);
    95     }
    96     return 0;
    97 }
    AC代码
  • 相关阅读:
    汉语-词语-平目:百科
    汉语-词语-平昔:百科
    汉语-词语-平一:百科
    汉语-词语-平居:百科
    汉语-词语-平展:百科
    汉语-词语-平静:百科
    汉语-词语-平心:百科
    汉语-词语-平庸:百科
    汉语-词语-平常:百科
    1231 最优布线问题
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10589336.html
Copyright © 2020-2023  润新知