IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> leetcode第294场周赛巫师的总力量和——维护前缀和的前缀和 -> 正文阅读

[数据结构与算法]leetcode第294场周赛巫师的总力量和——维护前缀和的前缀和

主要记录一下On预处理,O1取任意区间前缀和的前缀和

题目

6077. 巫师的总力量和

在这里插入图片描述

解题思路

贪心从小到大考虑,每次计算以 a i a_i ai?为最小值时的贡献。

下面来看具体例子:

在这里插入图片描述

  1. 考虑 a 2 a_2 a2?作为最小值时的贡献
    区间 [ 1 , 2 ] , [ 1 , 3 ] , [ 1 , 4 ] , [ 1 , 5 ] , [ 2 , 2 ] , [ 2 , 3 ] , [ 2 , 4 ] , [ 2 , 5 ] [1,2],[1,3],[1,4],[1,5],[2,2],[2,3],[2,4],[2,5] [1,2],[1,3],[1,4],[1,5],[2,2],[2,3],[2,4],[2,5]
  2. 考虑 a 4 a_4 a4?作为最小值时的贡献
    区间 [ 3 , 4 ] , [ 4 , 4 ] , [ 4 , 5 ] , [ 3 , 5 ] [3,4],[4,4],[4,5],[3,5] [3,4],[4,4],[4,5],[3,5]
    如果我们计算区间 [ 1 , 4 ] [1,4] [1,4] [ 2 , 4 ] [2,4] [2,4],则与1中的贡献计算发生了重复。因此每次计算 a i a_i ai?的贡献时,左端点不超过上个值与 a i a_i ai?相同的位置,右端点到 n n n,但是,这样还不够,我们还要保证这些区间的最小值为 a i a_i ai?
  3. 考虑 a 3 a_3 a3?作为最小值时的贡献
    区间 [ 3 , 3 ] [3,3] [3,3]合法,因为之前枚举过的 a i a_i ai?都小于当前值,会分割数组。

接下来考虑如何计算区间贡献。我们不可能枚举所有区间,这样会超时,来观察上述步骤1中的贡献情况。

在这里插入图片描述
容易发现,以 a i a_i ai?为最小值的时候,左边元素的贡献次数为 1 次 , 2 次 , 3 次 . . . . . . 1次,2次,3次... ... 1,2,3......,左边元素的贡献次数为 . . . . . . 3 次 , 2 次 , 1 次 ... ...3次,2次,1次 ......3,2,1 a i a_i ai?本身贡献次数为 ( n u m l e f t + 1 ) × ( n u m r i g h t + 1 ) (num_{left}+1)\times(num_{right}+1) (numleft?+1)×(numright?+1)次。只需要确定区间的左右端点,就可以直接计算以 a i a_i ai?为最小值的所有区间的贡献。

a i a_i ai?两侧的贡献次数,满足前缀和的前缀和规律。右侧部分是从左向右的前缀和的前缀和。左侧部分是从右向左的后缀和的后缀和。如何快速计算任意区间的前缀和的前缀和呢?

来看下图。
在这里插入图片描述
初始化 : s 0 = s s 0 = 0 s_0 = ss_0=0 s0?=ss0?=0
前缀和: s i = s i ? 1 + a i s_i = s_{i-1}+a_i si?=si?1?+ai?
前缀和的前缀和: s s i = s s i ? 1 + s i ss_i = ss_{i-1}+s_i ssi?=ssi?1?+si?

结论:

s s l , r = s s r ? s s l ? 1 ? ( r ? l + 1 ) × s l ? 1 ss_{l,r}=ss_{r}-ss_{l-1}-(r-l+1)\times s_{l-1} ssl,r?=ssr??ssl?1??(r?l+1)×sl?1?

很容易验证结论的正确性,不再赘述。

这样一来,我们就可以 O ( n ) O(n) O(n)预处理之后, O ( 1 ) O(1) O(1)得到任意区间的前缀和的前缀和

后缀同理。

AC代码

const long long N = 1e5 + 5;
const long long mod = 1e9 + 7;

class Solution
{
public:
	map<long long, vector<long long>> pos;
	long long pre[N], suf[N], ppre[N], ssuf[N];
	set<long long> st;
	set<long long> vis;
	long long n;

	void init_ss(vector<int> &a)
	{
		int n = a.size() - 1;
		for (int i = 1; i <= n; i++)
			pre[i] = pre[i - 1] + a[i];
		for (int i = 1; i <= n; i++)
			ppre[i] = (ppre[i - 1] + pre[i]) % mod;
		for (int i = n; i >= 1; i--)
			suf[i] = suf[i + 1] + a[i];
		for (int i = n; i >= 1; i--)
			ssuf[i] = (ssuf[i + 1] + suf[i]) % mod;
	}

	long long getlr(int l, int r)
	{
		long long len = r - l + 1;
		return (ppre[r] - (ppre[l - 1] + pre[l - 1] * len) % mod + mod) % mod;
	}
	long long getrl(int r, int l)
	{
		long long len = r - l + 1;
		return (ssuf[l] - (ssuf[r + 1] + suf[r + 1] * len) % mod + mod) % mod;
	}

	long long totalStrength(vector<int> &a)
	{

		n = a.size();
		a.insert(a.begin(), -1);

		init_ss(a);

		vis.insert(0);
		vis.insert(n + 1);

		for (long long i = 1; i <= n; i++)
		{
			st.insert(a[i]);
			pos[a[i]].emplace_back(i);
		}

		long long ans = 0;
		for (auto val : st)
		{
			long long m = pos[val].size();
			for (long long i = 0; i < m; i++)
			{
				long long p = pos[val][i];
				auto iter = vis.upper_bound(p);
				long long rr = (*iter) - 1;
				iter--;
				long long ll = (*iter) + 1;

				long long lenL = p - ll + 1;
				long long lenR = rr - p + 1;

				long long num, v;
				num = lenL;
				v = getlr(p, rr);
				ans = (ans + num * v % mod * val) % mod;
				num = lenR;
				v = getrl(p, ll);
				ans = (ans + num * v % mod * val) % mod;
				num = lenR * lenL % mod;
				v = val;
				ans = (ans - num * v % mod * val % mod + mod) % mod; //减去重复贡献
				vis.insert(p);
			}
		}
		return ans;
	}
};
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-24 18:28:42  更:2022-05-24 18:31:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 1:30:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码