https://vjudge.net/problem/CodeForces-1304D
题目大意:给出长度为 n − 1 n-1 n−1的仅有 > 、 < >、< >、<构成的字符串,若 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[i−1],那么 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;
}