标签:大于号 div2 strong 就是 从后往前 cout 这一 clu --
0.首先思考什么时候产生LIS上升的贡献,肯定是遇到了一个小于号啊,左边 < 右边。就产生贡献2
举例:比如 3<5 那么产生了贡献的长度为2; 再比如 5>4 大于号肯定不产生LIS的贡献了,。
假设上面想到了。
接下来考虑怎么找最短,和最长。
再等等,思考还有没有产生贡献的地方?
容易想到就是** 小于号 与 小于号 之间 也会产生贡献。**
比如 3<5>4<6; 那么3,5,6这三个数就产生了贡献,即两个小于号也可能产生贡献。
1.考虑找最短,有了上面的思考,容易想到,一个小于号产生的贡献我们肯定无法改变了,那么考虑“小于号与小于号之间”的贡献我们怎么把它给减小;
容易想到,如果 前面的小于号左右两边值,比,后面的小于号左右两边值大,那么这样就能消除 “小于号与小于号之间的贡献”
比如 3<5>2<1, 这样3,5,1就不能构成LIS,只有3,5能构成LIS,产生贡献2;
比如 3<5>4<6,这样3,5,6都能构成LIS,产生贡献3;
所以我们,就把数字从大往小放,这样能保证“小于号与小于号之间不构成LIS”
用双指针,每次以连续小于号为一组,从这一组的最后开始往前放数字(数字从大到小),这样能保证小于号与小于号之间不构成LIS,使之最短。
总结:尽量使大的数在前面
2.考虑找最长,同上理解,
所以我们,就把数字从小往大放,这样能保证“小于号与小于号之间也构成LIS”
用双指针,每次以连续大于号为一组,从这一组的最后开始往前放数字(数字从小到后),这样能保证小于号与小于号之间构成LIS,使之最长。
为什么这里以大于号为一组呢,因为我们是从小往后放数字的,为了保证小于号之间是能产生贡献的
总结:尽量使小的数在前面。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
int t;
int n;
string s;
int mina[maxn],maxb[maxn];
int main(){
cin>>t;
while(t--){
cin>>n;
cin>>s;
//找最短
int maxNum = n; //从大往前放 就能确保各个小于号 大的在前 小的数在后
for(int i=0;i<s.length();i++){
int len = 0;
if(s[i] == '<'){ //找连续的小于号
while(s[i] == '<'){
len++;
i++;
}
}
//从后往前放数字 以保证后面大前面小
for(int j=i;j>=i-len;j--){
mina[j] = maxNum--;
}
}
if(maxNum != 0) mina[n-1] = maxNum;
//找最长
int minNum = 1; //从小的数开始放 就能确保 各个小于号, 小的在前 大的在后 这样就能产生递增的贡献
for(int i=0;i<s.length();i++){
int len = 0;
if(s[i] == '>'){
while(s[i] == '>'){
len++;
i++;
}
}
//从后往前放数字 以保证后面小前面大
for(int j=i;j>=i-len;j--){
maxb[j] = minNum++;
}
}
if(minNum == n) maxb[n-1] = n;
for(int i=0;i<=n-1;i++) cout<<mina[i]<<" ";
cout<<endl;
for(int i=0;i<=n-1;i++) cout<<maxb[i]<<" ";
cout<<endl;
}
return 0;
}
/*
3
3 <<
7 >><>><
5 >>><
*/
感觉自己挺废的,想了一两个小时没想出来,看了题解才知道,真的废啊啊啊
这样也好,看完题解,按自己的方式理解,总比不写好,不写永远不知道自己有多菜,虽然一下午就干这一道题了。
自己选择的路,好好走完吧。
CF-div2-620-D. Shortest and Longest LIS 贪心,双指针
标签:大于号 div2 strong 就是 从后往前 cout 这一 clu --
原文地址:https://www.cnblogs.com/fisherss/p/12383899.html