codeforces 1304D Shortest and Longest LIS 构造 贪心

https://vjudge.net/problem/CodeForces-1304D
在这里插入图片描述在这里插入图片描述

题目大意:给出长度为 n − 1 n-1 n1的仅有 > 、 < >、< ><构成的字符串,若 s [ i ] = “ > ” s[i]=“>” s[i]=>,说明 a [ i ] > a [ i + 1 ] a[i]>a[i+1] a[i]>a[i+1],否则说明 a [ i ] < a [ i + 1 ] a[i]<a[i+1] a[i]<a[i+1],且 1 < = a [ i ] < = n 1<=a[i]<=n 1<=a[i]<=n,让你构造出两个序列,在满足上述限制的情况下,第一个序列的 L I S LIS LIS最短,第二个序列的 L I S LIS LIS最长。

思路:我们转换一下思路,如果 a [ i ] > a [ i − 1 ] a[i]>a[i-1] a[i]>a[i1],那么 t [ i ] = 1 t[i]=1 t[i]=1,否则 t [ i ] = 0 t[i]=0 t[i]=0,这样就把原字符串 s s s转换成了一个 01 01 01 t t t,那么对于 t t t中连续的 1 1 1 0 0 0来说,用连续的数字构造是最优的。比如 t = 0000 t=0000 t=0000,那么构造出来的结果是 4321 4321 4321,而且连续的 0 0 0一定对 L I S LIS LIS没有贡献,所以我们先逆序处理 t t t,若 t [ j ] = 0 t[j]=0 t[j]=0,且它是第 i i i 0 0 0,那么构造 b [ j ] = i b[j]=i b[j]=i。处理完之后就只剩下连续的 1 1 1了,如果要使 L I S LIS LIS最长,那么自然想把这些 1 1 1全部连起来,也就是正序处理 t t t,逐一递增;如果要使 L I S LIS LIS最短,那么自然想让这些 1 1 1连不起来,也就是正序处理 t t t,逐一递减(这里指的是一大块和另一大块的关系,同一块内由于限制必须是递增的)。

#include<bits/stdc++.h>
#define pr pair<int,int>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

const int maxn=2e5+5;

int t,n;
int a[maxn],ans[2][maxn];
char s[maxn];

int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        scanf("%s",s);
        a[0]=1;
        for(int i=1;i<n;i++)
        {
            if(s[i-1]=='>')
                a[i]=0;
            else
                a[i]=1;
        }
        int j=1;
        for(int i=n-1;i>=0;i--)
            if(!a[i])
                ans[0][i]=ans[1][i]=j++;
        for(int i=0;i<n;i++)
            if(a[i])
                ans[1][i]=j++;
        for(int i=0,v=n;i<n;i++)
        {
            if(a[i])
            {
                int j=i+1;
                while(a[j]&&j<n)
                    ++j;
                for(int k=j-1;k>=i;k--)
                    ans[0][k]=v--;
                i=j-1;
            }
        }
        for(int i=0;i<2;i++)
        {
            for(int j=0;j<n;j++)
                printf("%d ",ans[i][j]);
            printf("\n");
        }
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值