zoukankan      html  css  js  c++  java
  • CF-div2-620-D. Shortest and Longest LIS 贪心,双指针

    思路

    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 >>><
    */
    

    思考人生

    感觉自己挺废的,想了一两个小时没想出来,看了题解才知道,真的废啊啊啊
    这样也好,看完题解,按自己的方式理解,总比不写好,不写永远不知道自己有多菜,虽然一下午就干这一道题了。
    自己选择的路,好好走完吧。

  • 相关阅读:
    UVa 11991 Easy Problem from Rujia Liu?
    UVa 11995 I Can Guess the Data Structure!
    LA 3485 (积分 辛普森自适应法) Bridge
    LA 5009 (三分法求极值) Error Curves
    软帝学院:一万字的Java基础知识总结大全(实用)
    学java可以做些什么
    从零开始学习java一般需要多长时间?
    学习java需要英语很好吗?
    java的8种基本数据类型
    什么是java变量,java变量是什么
  • 原文地址:https://www.cnblogs.com/fisherss/p/12383899.html
Copyright © 2011-2022 走看看