1144 DIV3:G - Two Merged Sequences(贪心 or dp +思维)

27 篇文章 0 订阅

1144 DIV3:G - Two Merged Sequences(贪心 or dp +思维)

积累思维。
题目大意:给一个序列,让你从中在不破坏原顺序的情况挑出一些数来,使得这个序列分成两份,第一份是严格递增,第二份严格递减。
若有解 第一行输出YES
第二行,若一个元素你将他放在递增序列内,则输出1,否则输出0。
若无解,输出NO

思路历程:一个序列要按原顺序分成一份递增,另一份递减,不难想到LIS,因为LIS也是在一个序列内选出尽量多的递增的元素。但这题要求剩余元素必须递减。考虑贪心的情况LIS可以取出尽量多的元素构成递增序列,使得用来构造递减序列的元素尽量少,但这好像对解题没有帮助,且nlogn的模板不能打印方案。放弃LIS
考虑每个元素的决策,很单一,要么将它放在递增序列,要么将它放在递减序列,瞬间想到了搜索。既然能搜索多半能dp,可是该怎么dp,状态是什么,dp出来怎么输出方案。又被卡住了,思考一会,认为dp可能搞不出来。遂放弃dp思路。

考虑决策上贪心,每个元素如果能能在递增序列或递减序列,该怎么放?考虑我们希望尽可能有解,那么维护一下每个值后面比他大的连续的序列长度,和比他小的连续的序列长度,比较权衡一下。又回到了和LIS类似的问题,而LIS nlogn模板用不了,n^2的解法超时,且这个贪心的方案还没有验证正确性。不用想了,直接放弃这种贪心。

好了,没思路了。

题解是这样的:有多种解法,考虑贪心的解法(dp的解法以后再补)。
对于每个元素,有两种可能的决策。那么维护两个序列,一个是递增的,一个是递减的。对于当前元素ai,如果 ai 只能放在其中一个序列,那么就直接放入那个唯一可放入的序列,如果两个都放不了,那么就没方案了 输出“NO"。如果两个都可以放,那么考虑下一个元素 ai+1,如果ai+1 > ai 那么我们把ai放入递增序列,否则把ai放入递减序列。如果ai+1 > ai,我们把ai放入递增序列可以使得ai+1有更多选择,更可能得出解。反之如果放入递减序列,那么ai+1一定只能放入递增序列。如果ai+1 < ai ,把ai放入递减序列那么ai+1既可以放入递增序列也可以放入递减序列,把ai放入递增序列那么ai+1只能放入递减序列。如果ai+1 = ai,那么这两个只能错开放,ai放哪里都是一样的。
因为题目只要求得出一个解,如果我们贪心使得下一个元素的决策方向尽可能的多,我们就更可能得出一个解。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
int a[maxn],vis[maxn];
vector<int> g,h;
int n;
int main(){
	scanf("%d",&n);
	for(int i = 1; i <= n; i++){
		scanf("%d",&a[i]);
	}
	int t1,t2;
	for(int i = 1; i <= n; i++){
		t1 = g.size();
		t2 = h.size();
		if(t1 == 0 || g[t1 - 1] < a[i]){
			if(t2 == 0 || h[t2 - 1] > a[i]){
				if(a[i + 1] > a[i]){
					g.push_back(a[i]);
					vis[i] = 0;
				}
				else{
					h.push_back(a[i]);
					vis[i] = 1;
				}
			}
			else{
				g.push_back(a[i]);
				vis[i] = 0;
			}
		}
		else{
			if(t2 == 0 || h[t2 - 1] > a[i]){
				h.push_back(a[i]);
				vis[i] = 1;
			}
			else{
				puts("NO");
				return 0;
			}
		}
	}
	puts("YES");
	for(int i = 1; i <= n; i++){
		printf("%d ",vis[i]);
	}
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值