[CodeForces - 1304D] Shortest and Longest LIS【构造序列】

题意:n-1个'>''<'的字符串,我们要构造一个长度为n的包含整数[1, n]的序列a[ ]。对于每个s[ i ] == '<'表示a[ i ] < a[ i + 1 ],对于s[ i ] == '>'表示a[ i ] > a[ i + 1 ]。我们找到两个满足条件的序列,输出一个LIS最短的序列,输出一个LIS最长的序列。

思路

我们将'<'用1替代,将'>'用0替代,构造一个01串,并且在该01串的首位置加一个1. 于是我们得到了一个长度为n的01串。

0代表什么呢?所有0都是连续的下降序列!

1代表什么呢?

  1. 如果对于所有的1,我们是连续的上升序列,显然可以得到最长的LIS
  2. 如果对于所有的“1的块”,每个块单调递减【块内连续上升;块间,每个块内最大值递减】

举个栗子

8 >><>><<
 10010011
  43 21   
 5  6  78
 8  7  56
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

inline int read()
{
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -f; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}

const int maxN = 200005;
int n;
int ans[2][maxN];
char s[maxN];
struct node{
    int l, r;
    node() {}
    node(int a, int b): l(a), r(b) {}
}info[maxN];

int main()
{
    int TAT; TAT = read();
    while(TAT --)
    {
        n = read();
        scanf("%s", s);
        int tot = 0, last = 1, now = 1;
        string _01 = "1";
        for(int i = 0; i < n - 1; ++ i )
            if(s[i] == '<')
                _01 += '1';
            else
                _01 += '0';
        for(int i = 0; i < n; ++ i )
        {
            if(_01[i] == '1')
            {
                if(last)
                    info[tot].r = i;
                else
                    info[++ tot] = node(i, i), last = 1;
            }
            else
                last = 0;
        }
        for(int i = n - 1; i >= 0; -- i)
            if(_01[i] == '0') ans[0][i] = ans[1][i] = now ++;
        int tmp = now;
        //处理最长上升子序列
        for(int i = 0; i <= tot; ++ i )
        {
            for(int j = info[i].l; j <= info[i].r; ++ j )
                ans[1][j] = tmp ++;
        }
        //处理最短上升子序列
        tmp = now;
        for(int i = tot; i >= 0; -- i)
        {
            for(int j = info[i].l; j <= info[i].r; j ++ )
                ans[0][j] = tmp ++ ;
        }
        for(int i = 0; i < n; ++ i )
            printf("%d%c", ans[0][i], " \n"[i == n - 1]);
        for(int i = 0; i < n; ++ i )
            printf("%d%c", ans[1][i], " \n"[i == n - 1]);
    }
    return 0;
}
发布了242 篇原创文章 · 获赞 68 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_44049850/article/details/104407662