首页 > 其他分享 >[ABC234G] Divide a Sequence

[ABC234G] Divide a Sequence

时间:2024-09-26 19:22:50浏览次数:10  
标签:Divide Sequence int max leq st ABC234G MAXN dp

[ABC234G] Divide a Sequence

给定长度为 \(N\) 的序列 \(A\),我们定义一种将 \(A\) 划分为若干段的方案的价值为每一段的最大值减去最小值的差的乘积,你需要求出所有划分方案的价值的总和,答案对 \(998244353\) 取模。

  • $ 1\ \leq\ N\ \leq\ 3\ \times\ 10^5 $
  • $ 1\ \leq\ A_i\ \leq\ 10^9 $

先考虑朴素 \(dp\),设 \(dp_i\) 为划分序列 \(A\) 的前 \(i\) 项所有划分方案的总和,则容易得到转移方程式:

\[dp_i = \sum^{i - 1}_{x = 1} dp_x \times \{ \max^{i}_{k = x + 1}\{a_k\} + \min^{i}_{k = x + 1}\{a_k\} \} \]

复杂度 \(O(n^2)\) 考虑优化。

首先拆分式子:

\[dp_i = \sum^{i - 1}_{x = 1}dp_x \times \{\max^{i}_{k = x + 1}\{a_k\}\} + \sum^{i - 1}_{x = 1} dp_x \times \{\min^{i}_{k = x + 1}\{a_k\}\} \]

分成 \(max\) 和 \(min\) 的两个子问题处理。

我们这里单单考虑 \(max\) 的情况:

对于 \(dp_i \to dp_{i + 1}\) 转移的情况,容易发现:

\[\max^{i}_{k = x + 1}\{a_k\} \]

这个式子的值只会在 \(x > pos\) (其中 \(pos\) 为 \(a_{i + 1}\) 前第一个比 \(a_{i + 1}\) 大的数的下标位置)的那些 \(x\) 值时会改变。

而\(a_{i + 1}\) 前第一个比 \(a_{i + 1}\) 大的数的下标位置我们可以用单调栈 \(O(n)\) 的复杂度预处理完成。

代码:

#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
#define int long long
const int MOD = 998244353;
const int MAXN = 3e5 + 7;
int n;
int a[MAXN];
int idmax[MAXN],idmin[MAXN];
stack<int> st;
void init(){
	for(int i = 1;i <= n;i++){
		while(!st.empty() && a[st.top()] <= a[i]){
			st.pop();
		}
		if(st.empty()) idmax[i] = 0;
		else idmax[i] = st.top();
		st.push(i);
	}
	while(!st.empty()) st.pop();
	for(int i = 1;i <= n;i++){
		while(!st.empty() && a[st.top()] >= a[i]){
			st.pop();
		}
		if(st.empty()) idmin[i] = 0;
		else idmin[i] = st.top();
		st.push(i);
	}
	while(!st.empty()) st.pop();
}
int dp[MAXN];
int predp[MAXN];
int maxx[MAXN],minn[MAXN];
signed main(){
	// ios::sync_with_stdio(false);
	// cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i = 1;i <= n;i++) cin>>a[i];
	init();
	dp[0] = predp[0] = 1;
	// for(int i = 1;i <= n;i++) cout<<idmin[i]<<" ";
	for(int i = 1;i <= n;i++){
		if(idmax[i]) maxx[i] = (maxx[idmax[i]] + (predp[i - 1] - predp[idmax[i] - 1]) * a[i]) % MOD;
		else maxx[i] = (predp[i - 1] * a[i]) % MOD;
		if(idmin[i]) minn[i] = (minn[idmin[i]] + (predp[i - 1] - predp[idmin[i] - 1]) * a[i]) % MOD;
		else minn[i] = (predp[i - 1] * a[i]) % MOD;
		dp[i] = ((maxx[i] - minn[i]) % MOD + MOD) % MOD;
		predp[i] = (predp[i - 1] + dp[i]) % MOD;
	}
	// for(int i = 1;i <= n;i++) cout<<dp[i]<<" "<<predp[i]<<endl;
	cout<<dp[n];
	return 0;
}

标签:Divide,Sequence,int,max,leq,st,ABC234G,MAXN,dp
From: https://www.cnblogs.com/wyl123ly/p/18434132

相关文章

  • WPF Error XLS0108 Entity references or sequences beginning with an ampersand '&'
    //https://img1.baidu.com/it/u=3991277133,2041185316&fm=253 <ImageSource="https://img1.baidu.com/it/u=3991277133,2041185316&fm=253"/>SeverityCodeDescriptionProjectFileLineSuppressionStateDetailsErr......
  • Luogu_P10977(AcWing_299) Cut the Sequence 题解
    解题思路考虑线性dp。首先如果存在\(a_i>m\),那肯定不满足条件,输出\(-1\)。设\(f_i\)表示前\(i\)个数分成若干段,然后每段最大数之和,其中每段内的整数之和不超过\(m\)。\(f_i\)肯定是由\(f_j\)(\(1\lej<i\))转移过来的,也就是前\(j\)个数分好后再加上\((j,i]\)这一......
  • CF2003F Turtle and Three Sequences 题解
    个人觉得*2800有点虚高。如果做过类似的题(比如[THUSCH2017]巧克力),应该可以想到随机映射,状压dp也不难想。实际上,看到要选出\(m\)种不同的颜色,且\(m\le5\)就可以想到将每种颜色随机映射到\(1\)到\(m\)中,这样子得出来的答案不会更优,而当答案选择的\(m\)种颜色恰好......
  • Oracle2PG sequence(序列)问题汇总
    迁移PostgreSQL的Sequence(序列)问题https://masuit.net/2042?t=0HN6FQRQT1K6P如何快速获取同步序列的SQL有些项目中数据量比较少,在迁移过程;表数据迁移过去;但是序列需要重置下;接下来讲到,引用自:https://www.cnblogs.com/lottu/p/14330474.htmlSELECTconcat('SELECTsetval(''"',......
  • OpenCV(cv::divide())
    目录1.函数定义2.工作原理3.示例3.1矩阵除法3.2矩阵和标量的除法3.3使用缩放因子4.注意事项5.应用场景cv::divide()是OpenCV中用于执行数组或标量的逐元素除法操作的函数。它允许对矩阵进行元素级的除法操作,支持两种使用方式:矩阵与矩阵之间的除法,或矩阵与标量之间的......
  • Rainbow Bracket Sequence
    The2024ICPCAsiaEastContinentOnlineContest(I)题意构造长度为\(2n\)的合法括号序列。对于每个左括号在的位置\(i\),都有颜色\(c_i\)和价值\(v_i\)。左括号颜色视为所在位置颜色,价值同理。对于每个颜色,满足左括号为该颜色的个数\(\geql_i\)。求满足以上......
  • Rainbow Bracket Sequence
    括号序列匹配+最优化问题+一系列限制条件+较小的数据范围=最小费用最大流模型拆点难以解决重复的问题,既然如此那就不拆点了,用流向代表左右括号的选择每一次bfs,总流量增加,总费用也是增加的,但是退流的边还是要归还费用【直觉就不对劲呀,多想一下吧】注意,当li的限制超过节点总数时......
  • CF1144G Two Merged Sequences
    首先我们考虑最暴力的方法,仿照着LIS板子题设计状态:\(dp_{i,j}\)表示考虑前\(\max(i,j)\)个,单减序列以\(i\)结尾,单增序列以\(j\)结尾,然后进行\(O(1)\)的转移。但是这样状态数就爆炸了,如何优化状态数呢?我们考虑进行换维。因为我们刚刚设计的是一个弱鸡的可行性DP,很强......
  • Java零基础-replace(CharSequence target, CharSequence replacement)详解
    哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者......
  • [AGC003E] Sequential operations on Sequence
    题意给定一个整数序列,有\(q\)次操作,每次操作从无限复制的序列里面选择前\(q_i\)个元素作为当前的序列。问\(1\)到\(n\)每个整数在最终序列中出现的次数。\(n\le10^5,q_i\le10^{18}\)Sol想象一下每次操作,都是复制若干次前一次的序列然后拼上一段余数组成的。......