D. Shortest and Longest LIS

题目描述

Gildong recently learned how to find the longest increasing subsequence (LIS) in O(n\log{n})O(nlogn) time for a sequence of length nn . He wants to test himself if he can implement it correctly, but he couldn't find any online judges that would do it (even though there are actually many of them). So instead he's going to make a quiz for you about making permutations of nn distinct integers between 11 and nn , inclusive, to test his code with your output.

The quiz is as follows.

Gildong provides a string of length n-1n−1 , consisting of characters '<' and '>' only. The ii -th (1-indexed) character is the comparison result between the ii -th element and the i+1i+1 -st element of the sequence. If the ii -th character of the string is '<', then the ii -th element of the sequence is less than the i+1i+1 -st element. If the ii -th character of the string is '>', then the ii -th element of the sequence is greater than the i+1i+1 -st element.

He wants you to find two possible sequences (not necessarily distinct) consisting of nn distinct integers between 11 and nn , inclusive, each satisfying the comparison results, where the length of the LIS of the first sequence is minimum possible, and the length of the LIS of the second sequence is maximum possible.

输入格式

Each test contains one or more test cases. The first line contains the number of test cases tt ( 1 \le t \le 10^41≤t≤104 ).

Each test case contains exactly one line, consisting of an integer and a string consisting of characters '<' and '>' only. The integer is nn ( 2 \le n \le 2 \cdot 10^52≤n≤2⋅105 ), the length of the permutation you need to find. The string is the comparison results explained in the description. The length of the string is n-1n−1 .

It is guaranteed that the sum of all nn in all test cases doesn't exceed 2 \cdot 10^52⋅105 .

输出格式

For each test case, print two lines with nn integers each. The first line is the sequence with the minimum length of the LIS, and the second line is the sequence with the maximum length of the LIS. If there are multiple answers, print any one of them. Each sequence should contain all integers between 11 and nn , inclusive, and should satisfy the comparison results.

It can be shown that at least one answer always exists.

题意翻译

题目描述

给你一个有 n(2 \le n \le 2\cdot 10^5)n(2≤n≤2⋅105) 个元素的排列 AA 中,每相邻两个元素的大小关系,要你构造出两组解,使得第一组解的 LIS 最短,第二组解的 LIS 最长。

输入格式

第一行共一个整数 t(1 \le t \le 10^4)t(1≤t≤104),表示数据组数。

每组数据包含一个整数 nn 以及一个长度为 n - 1n−1 的字符串 \text{S}S。

其中 S[i] == '<' 表示 A_i < A_{i + 1}Ai​<Ai+1​,S[i] == '>' 表示 A_i > A_{i + 1}Ai​>Ai+1​。

保证所有数据中所有 nn 之和不超过 2\cdot 10^52⋅105。

输出格式

输出共 2t2t 行。

第 2i + 12i+1 行和第 2i + 22i+2 行表示第 ii 组数据的答案。

第 2i + 12i+1 行表示第 ii 组数据中 LIS 最短的解,第 2i + 22i+2 行表示第 ii 组数据中 LIS 最长的解。

若有多组解,可以输出其中的任意一种。

可以证明至少存在 11 组解。

输入输出样例

输入 #1复制

3
3 <<
7 >><>><
5 >>><

输出 #1复制

1 2 3
1 2 3
5 4 3 7 2 1 6
4 3 1 7 5 2 6
4 3 2 1 5
5 4 2 1 3

说明/提示

In the first case, 11 22 33 is the only possible answer.

In the second case, the shortest length of the LIS is 22 , and the longest length of the LIS is 33 . In the example of the maximum LIS sequence, 44 ' 33 ' 11 77 ' 55 ' 22 ' 66 ' can be one of the possible LIS.


思路:

先考虑最小的LIS.观察到"<"必然产生一对长度为2的lis,如果没有<,就可以不产生LIS。所以贪心去思考,尽量在前面能放大的数就放大的数,这样由'<"产生的lis的数字是更小的,不会和前面的数字产生多的lis。

考虑最大的lis,由Dirworth定理得,最长上升子序列长度等于下降子序列的个数,所以出现">"肯定会出现下降的子序列,要让能出现下降序列的个数尽可能多。所以在前面能放小的数就尽量放小的数,这样后面的数相对较大,和前面划分出来就得多出一些下降子序列的条数。

然后就是模拟的过程

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=2e5+100;
typedef long long LL;
char s[maxn];
LL a[maxn];
void init(LL n)
{
	for(LL i=0;i<=n+10;i++) a[i]=0; 
}
void solve()
{
	LL n;cin>>n;
	init(n+10);
	memset(s,0,sizeof(s));
	cin>>(s+1);s[n]='#';
	LL m=n;
	for(LL i=1;i<=n;i++){
		if(s[i]=='>'&&!a[i]||s[i]=='#')
		{
			a[i]=m;m--;	
		}		 
		else if(s[i]=='<'&&!a[i])
		{
			LL pos=i;
			while(s[i]=='<'&&!a[i])	i++;
			for(LL j=i;j>=pos;j--)
			{
				a[j]=m;m--;
			}
		}
	}
	for(LL i=1;i<=n;i++) cout<<a[i]<<" ";
	cout<<endl;
	init(n+10);
	m=1;
	for(LL i=1;i<=n;i++)
	{
		if(s[i]=='<'&&!a[i]||s[i]=='#')
		{
			//debug(a[i]);
			a[i]=m;m++;	
		} 
		else if(s[i]=='>'&&!a[i])
		{
			LL pos=i;
			while(s[i]=='>'&&!a[i]) i++;
			for(LL j=i;j>=pos;j--)
			{
				a[j]=m;m++;	
			}		
		}
	}
	for(LL i=1;i<=n;i++) cout<<a[i]<<" ";
	cout<<endl;
} 
int main(void)
{
  LL t;cin>>t;
  while(t--)
  {
  	solve();	
  }
return 0;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/108389508