D. Shortest and Longest LIS(构造+dirworth定理)

Problem - 1304D - Codeforces

Gildong最近学会了如何在O(nlogn)时间内找到长度为n的序列的最长递增子序列(LIS)。他想测试一下自己是否能正确实现,但他在网上找不到任何能做到的裁判(尽管实际上有很多)。因此,他要为你做一个关于对1到n之间的n个不同的整数进行排列组合的测验,用你的输出来测试他的代码。

测验的内容如下。

Gildong提供了一个长度为n-1的字符串,仅由字符'<'和'>'组成。第i个(1-索引)字符是序列中第i个元素和第i+1个元素之间的比较结果。如果字符串的第i个字符是'<',那么序列的第i个元素就小于第i+1个元素。如果字符串的第i个字符是'>',那么序列的第i个元素就大于第i+1个元素。

他想让你找到两个可能的序列(不一定是不同的),由1到n之间的n个不同的整数组成,每个都满足比较结果,其中第一个序列的LIS的长度是最小可能,第二个序列的LIS的长度是最大可能。

输入
每个测试包含一个或多个测试案例。第一行包含测试用例的数量t(1≤t≤104)。

每个测试用例正好包含一行,由一个整数和一个仅由字符'<'和'>'组成的字符串组成。整数是n (2≤n≤2⋅105),你需要找到的排列组合的长度。字符串是描述中解释的比较结果。字符串的长度为n-1。

保证所有测试案例中所有n的总和不超过2⋅105。

输出
对于每个测试案例,打印两行,每行有n个整数。第一行是具有最小长度的LIS的序列,第二行是具有最大长度的LIS的序列。如果有多个答案,打印其中任何一个。每个序列应该包含1到n之间的所有整数,包括在内,并且应该满足比较的结果。

可以证明,至少有一个答案总是存在的。

例子
输入复制
3
3 <<
7 >><>><
5 >>><
输出拷贝
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
注意
在第一种情况下,1 2 3是唯一可能的答案。

在第二种情况下,最短的LIS长度是2,最长的LIS长度是3。在最大LIS序列的例子中,4 '3' 1 7 '5' 2 '6' 可以是可能的LIS之一。

题意:给你一个数字n,与一串长为n-1的字符串,只包括<与>,构建一个最短上升子序列,与最长上升子序列,通过n的排列组合

题解:构建最短上升子序列时,我们应该让尽量大的数放在前面,遇到<时改变,

构建最长上升子序列时,根据(dirworth定理)

最长上升子序列的长度为,非上升子序列的个数(在这题里就是下降子序列的个数)

应让尽量小的数在前,遇到>时改变

#include<iostream>
#include<string>
using namespace std;
int ans1[200050],ans2[200050];
int main()
{
	int t;
	cin >> t;
	while(t--)
	{
		int n;
		string s;
		cin >>n >>s; 
		int m = n;
		for(int i = 0;i < n;i++)
		{
			int len = 1;
			while(i < n&&s[i] == '<')
			{
				len++;
				i++; 
			}
			for(int j = i;j > i-len;j--)
			ans1[j] = m--;
			
		}
		m  = 1;
		for(int i = 0; i < n;i++)
		{
			int len = 1;
			while(i < n&s[i]=='>')
			{
				len ++;
				i++; 
			}
			for(int j = i;j > i-len;j --)
			ans2[j] = m++;
		}
		for(int i =0; i <n;i++)
		cout<<ans1[i] <<" ";
		printf("\n");
		for(int i =0; i <n;i++)
		cout<<ans2[i] <<" ";
		printf("\n");		 
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值