CF1304D Shortest and Longest LIS
Posted chinesepikaync
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1304D Shortest and Longest LIS相关的知识,希望对你有一定的参考价值。
一种很巧妙的做法
我们从第二个样例开始讲
想要 LIS 最小,我们就先这样放置
7 6 5 4 3 2 1
然后如果碰到一连串的小于号,那就把那一段小于号所在的数字段整段翻转
也就是说
> > < > > <
7 6 4 5 3 1 2
第一个小于使得 4 5
被翻转,第二个 <
使得 1 2
被翻转
这样 LIS 就为最大连续小于号的长度,无论如何 LIS 都没办法小于这个
要想 LIS 最大,反过来就行了
先放置
1 2 3 4 5 6 7
如果碰到一连串的大于号,那就把那一段大于号所在的数字段整段翻转
> > < > > <
3 2 1 6 5 4 7
这样 LIS 就为连续小于号段的数量+1,无论如何 LIS 都没办法大于这个
于是就 (O(n)) 搞定了
// This code wrote by chtholly_micromaker(MicroMaker)
#include <bits/stdc++.h>
#define reg register
using namespace std;
/*
template <class t> inline void read(t &s)
{
s=0;
reg int f=1;
reg char c=getchar();
while(!isdigit(c))
{
if(c=='-')
f=-1;
c=getchar();
}
while(isdigit(c))
s=(s<<3)+(s<<1)+(c^48),c=getchar();
s*=f;
return;
}
*/
char s[200050];
int a[200050];
inline void myrev(int l,int r)
{
reg int delta=l-1;
reg int n=r-l+1;
for(int i=1;i<=n/2;++i)
swap(a[delta+i],a[delta+n-i+1]);
return;
}
inline void work()
{
reg int n;
cin>>n;
cin>>(s+1);
for(int i=1;i<=n;++i)
a[i]=n-i+1;
reg int cnt=0;
for(int i=1;i<n;++i)
if(s[i]=='<')
++cnt;
else if(cnt)
myrev(i-cnt,i),cnt=0;
if(cnt)
myrev(n-cnt,n);
for(int i=1;i<=n;++i)
cout<<a[i]<<" ";
cout<<endl;
for(int i=1;i<=n;++i)
a[i]=i;
cnt=0;
for(int i=1;i<n;++i)
if(s[i]=='>')
++cnt;
else if(cnt)
myrev(i-cnt,i),cnt=0;
if(cnt)
myrev(n-cnt,n);
for(int i=1;i<=n;++i)
cout<<a[i]<<" ";
cout<<endl;
return;
}
signed main(void)
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int t;cin>>t;
while(t--)
work();
return 0;
}
以上是关于CF1304D Shortest and Longest LIS的主要内容,如果未能解决你的问题,请参考以下文章
[CF1304D] Shortest and Longest LIS - 贪心
CF 1005F Berland and the Shortest Paths
CF1005F Berland and the Shortest Paths 最短路树计数
CF-div2-620-D. Shortest and Longest LIS 贪心,双指针