牛牛的数列 NC13134 题解备忘

牛牛的数列

https://ac.nowcoder.com/acm/problem/13134

题号:NC13134 链接:https://ac.nowcoder.com/acm/problem/13134 来源:牛客网

牛牛现在有一个n个数组成的数列,牛牛现在想取一个连续的子序列,并且这个子序列还必须得满足:最多只改变一个数,就可以使得这个连续的子序列是一个严格上升的子序列,牛牛想知道这个连续子序列最长的长度是多少。

链接:https://ac.nowcoder.com/acm/problem/13134 来源:牛客网

输入包括两行,第一行包括一个整数n(1 ≤ n ≤ 10^5),即数列的长度;

第二行n个整数a_i, 表示数列中的每个数(1 ≤ a_i ≤ 10^9),以空格分割。

输出一个整数,表示最长的长度。

本人较菜,不想针对题目进行研究考虑。

这道题也是典型的dp动态规划题目。

需要3个变量记录当前的状态:以当前值作为序列尾部时当前的序列最长长度,尾部值(或者下一值必须大于这个值的最小值),变化次数。

3个值确定一个状态。

状态a,b合并:如果变化次数一样,长度a>=长度b,且尾部值a<=尾部值b,那么状态a是可以替代状态b的。删掉状态b。

实际上,这个状态数量不会很多的。

另外:值为(1 ≤ a_i ≤ 10^9),无限小用0替代。

求解:出现这些状态中的序列最长长度便是答案。

附代码:

c++

#include <string.h>
#include <vector>
using namespace std;
typedef struct Node{
	int useNum;
	int maxLen;
	int lastV = 0;
} Node;


int main() {
	int n,a;
	cin >> n;
	Node dp1[100];
	Node dp2[100];
	int dp_top1 = 0;
	int dp_top2 = 0;
	Node t0,t1;
	int maxLen=0;
	for (int i = 0; i < n; i++) {
		cin >> a;
		dp_top2 = 0;
		// 当前的值作为第一个
		dp2[dp_top2].maxLen = 1;
		dp2[dp_top2].useNum = 0;
		dp2[dp_top2].lastV = a;
		dp_top2++;

		dp2[dp_top2].maxLen = 1;
		dp2[dp_top2].useNum = 1;
		dp2[dp_top2].lastV = 0;
		dp_top2++;

		// 当前的值不作为第一个
		for (int j = 0; j < dp_top1; j++) {
			for (int k = dp1[j].useNum; k <= 1; k++) {
				// 不改变当前的值
				if (dp1[j].lastV < a) {
					dp2[dp_top2].lastV = a;
					dp2[dp_top2].maxLen = dp1[j].maxLen + 1;
					dp2[dp_top2].useNum = dp1[j].useNum;
					dp_top2++;
				}
				// 改变当前的值
				if (dp1[j].useNum + 1 <= 1) {
					dp2[dp_top2].lastV = dp1[j].lastV;
					dp2[dp_top2].maxLen = dp1[j].maxLen + 1;
					dp2[dp_top2].useNum = dp1[j].useNum + 1;
					dp_top2++;
				}
			}
		}

		// 归并
		dp_top1 = 0;
		for (int j = 0; j < dp_top2; j++) {
			bool noNeed = false;
			for (int k = 0; k < dp_top1; k++) {
				if (dp2[j].useNum == dp1[k].useNum) {
					if (dp2[j].maxLen <= dp1[k].maxLen && dp2[j].lastV >= dp1[k].lastV) {
						noNeed = true;
						break;
					}
					else if (dp2[j].maxLen >= dp1[k].maxLen && dp2[j].lastV <= dp1[k].lastV) {
						noNeed = true;
						dp1[k] = dp2[j];
						break;
					}
				}
			}
			//printf("I: 是否需要%d len:%d lastV:%d useNum:%d\n", !noNeed, dp2[j].maxLen, dp2[j].lastV, dp2[j].useNum);
			if (!noNeed) {
				dp1[dp_top1++] = dp2[j];
				if (dp2[j].maxLen > maxLen) {
					maxLen = dp2[j].maxLen;
				}
			}
		}
		//for (int j = 0; j < dp_top1; j++) {
		//	printf("I: %d-->len:%d lastV:%d useNum:%d\n", j + 1, dp1[j].maxLen, dp1[j].lastV, dp1[j].useNum);
		//}
		//printf("\n");
	}
	printf("%d\n", maxLen);
}
全部评论

相关推荐

避坑恶心到我了大家好,今天我想跟大家聊聊我在成都千子成智能科技有限公司(以下简称千子成)的求职经历,希望能给大家一些参考。千子成的母公司是“同创主悦”,主要经营各种产品,比如菜刀、POS机、电话卡等等。听起来是不是有点像地推销售公司?没错,就是那种类型的公司。我当时刚毕业,急需一份临时工作,所以在BOSS上看到了千子成的招聘信息。他们承诺无责底薪5000元,还包住宿,这吸引了我。面试的时候,HR也说了同样的话,感觉挺靠谱的。于是,我满怀期待地等待结果。结果出来后,我通过了面试,第二天就收到了试岗通知。试岗的内容就是地推销售,公司划定一个区域,然后你就得见人就问,问店铺、问路人,一直问到他们有意向为止。如果他们有兴趣,你就得摇同事帮忙推动,促进成交。说说一天的工作安排吧。工作时间是从早上8:30到晚上18:30。早上7点有人叫你起床,收拾后去公司,然后唱歌跳舞(销售公司都这样),7:55早课(类似宣誓),8:05同事间联系销售话术,8:15分享销售技巧,8:30经理训话。9:20左右从公司下市场,公交、地铁、自行车自费。到了市场大概10点左右,开始地推工作。中午吃饭时间大约是12:00,公司附近的路边盖饭面馆店自费AA,吃饭时间大约40分钟左右。吃完饭后继续地推工作,没有所谓的固定中午午休时间。下午6点下班后返回公司,不能直接下班,需要与同事交流话术,经理讲话洗脑。正常情况下9点下班。整个上班的一天中,早上到公司就是站着的,到晚上下班前都是站着。每天步数2万步以上。公司员工没有自己的工位,百来号人挤在一个20平方米的空间里听经理洗脑。白天就在市场上奔波,公司的投入成本几乎只有租金和工资,没有中央空调。早上2小时,晚上加班2小时,纯蒸桑拿。没有任何福利,节假日也没有3倍工资之类的。偶尔会有冲的酸梅汤和西瓜什么的。公司的晋升路径也很有意思:新人—组长—领队—主管—副经理—经理。要求是业绩和团队人数,类似传销模式,把人留下来。新人不能加微信、不能吐槽公司、不能有负面情绪、不能谈恋爱、不能说累。在公司没有任何坐的地方,不能依墙而坐。早上吃早饭在公司外面的安全通道,未到上班时间还会让你吃快些不能磨蹭。总之就是想榨干你。复试的时候,带你的师傅会给你营造一个钱多事少离家近的工作氛围,吹嘘工资有多高、还能吹自己毕业于好大学。然后让你早点来公司、无偿加班、抓住你可能不会走的心思进一步压榨你。总之,大家在找工作的时候一定要擦亮眼睛,避免踩坑!———来自网友
qq乃乃好喝到咩噗茶:不要做没有专业门槛的工作
点赞 评论 收藏
分享
Southyeung:我说一下我的看法(有冒犯实属抱歉):(1)简历不太美观,给我一种看都不想看的感觉,感觉字体还是排版问题;(2)numpy就一个基础包,机器学习算法是什么鬼?我感觉你把svm那些写上去都要好一点。(2)课程不要写,没人看,换成获奖经历;(3)项目太少了,至少2-3个,是在不行把网上学习的也写上去。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务