Namomo Test Round 2 C序列 题解 个人理解

题目链接
题解链接
ps:此篇博客是对题解的个人理解,为了使以后看到这道题可以看懂,如果原作者认为此篇博客侵权了,请联系我删除
题解原文:
在这里插入图片描述
个人理解:
解释一:
在这里插入图片描述
首先来个图:
在这里插入图片描述
很容易发现,如果要按最小步骤得到的最大值,那么一定是如下的图:
操作次序为:红(1次),橙(3次),黄(1次),绿(3次)
在这里插入图片描述
从这里我们就可以发现结论:前括号划分的位置恰好都是在差分( a [ i + 1 ] − a [ i ] a[i + 1] - a[i] a[i+1]a[i])为正的位置,后括号划分的位置恰好都是在差分为负的位置

而按最小步骤得到的最大值则需各位自己画图理解(ps:可以发现括号的位置都是一样的,但是顺序却不同

综上,(主要是题解 ),我们就可以大胆猜测要想用最小步骤得到代价最小值以及最大值一定要满足上述结论

简单证明为啥这样是最少步骤且能得到最大值:
假设一个全不为0的序列,那么肯定一开始要对整个序列减一,如果一开始就不这样做,那么一定不会得到最优步骤,而且值肯定也会变小…(这只是粗略证明,详细证明,我好像并不会…)

至于为啥这样是最少步骤这样也能得到最小值,请自证(真是令人讨厌的词汇

解释二:
在这里插入图片描述

  • 假设已经求出所有括号的位置,即ai, bi那么根据题意,就能得到上图那个式子,再将其简单转换一下,得到如上等式

  • 根据我们小学二年级学的排序不等式,如果想求 r e s res res最大那么一定要满足在这里插入图片描述
    其次再满足
    在这里插入图片描述
    就能得到res的最大值
    通俗来讲就是:最远的那个后括号要与最前面的前括号对应

  • r e s res res最小,请自证
    解释三:
    在这里插入图片描述
    为啥最大值要用栈来维护a呢?

  • 因为栈是先进后出,所以能保证:最远的那个后括号要与最前面的前括号对应

同理可证为啥最小值要用队列维护a

AC代码:

// Test1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
typedef long long ll;
typedef pair <ll, ll> pi;
const int maxn = 500100;
const ll Mod = 1000000007;
ll a[maxn], res1, res2, n;
stack <pi> sta;//计算最大值
queue <pi> que;//计算最小值
int main() {
	ios::sync_with_stdio(false);
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];
	a[0] = a[n + 1] = 0;
	//算最小值
	for (int i = 0; i <= n; i++) {
		if (a[i + 1] - a[i] > 0) que.push(pi(i, a[i + 1] - a[i]));//前括号,队列维护
		else if (a[i + 1] - a[i] < 0) {//后括号
			ll tmp = a[i] - a[i + 1];
			while (tmp && que.front().second <= tmp) {
				res1 += que.front().second * (i - que.front().first) % Mod * (i - que.front().first) % Mod;
				res1 %= Mod;
				tmp -= que.front().second;
				que.pop();
			}
			if (tmp) {//如果不能抵消了,那么就不会弹出
				res1 += tmp * (i - que.front().first) % Mod * (i - que.front().first) % Mod;
				res1 %= Mod;
				que.front().second -= tmp;
			}
		}
	}
	//算最大值
	for (int i = 0; i <= n; i++) {
		if (a[i + 1] - a[i] > 0) sta.push(pi(i, a[i + 1] - a[i]));//栈维护
		else if (a[i + 1] - a[i] < 0) {
			ll tmp = a[i] - a[i + 1];
			while (tmp && sta.top().second <= tmp) {
				res2 += sta.top().second * (i - sta.top().first) % Mod * (i - sta.top().first) % Mod;
				res2 %= Mod;
				tmp -= sta.top().second;
				sta.pop();
			}
			if (tmp) {
				res2 += tmp * (i - sta.top().first) % Mod * (i - sta.top().first) % Mod;
				res2 %= Mod;
				sta.top().second -= tmp;
			}
		}
	}
	cout << res1 << " " << res2 << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值