主要记录一下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;}
};

leetcode第294场周赛巫师的总力量和——维护前缀和的前缀和相关推荐

  1. leetcode 第294场周赛题解

    rank 529 / 6640,第4题一共过了100 / 6640来人,基本上就是前三题比手速了: 第一题 .字母在字符串中的百分比 给你一个字符串 s 和一个字符 letter ,返回在 s 中等于 ...

  2. Leetcode之第294场周赛小记

    小记 本篇博客记录小黑第三次参加leetcode周赛(294场次)的成绩,以及对题目的总结,以便鞭策自己不断前进 . 这次周赛是我第三次参加,前两题比较简单,做起来也是非常顺利,只用了15分钟就完成解 ...

  3. 当单调栈遇到了前前缀和(Leetcode 2281. 巫师的总力量和、力扣第 294 场周赛第 4 题)

    2281. 巫师的总力量和(力扣第 294 场周赛第 4 题) 这道题做起来比较复杂.需要单调栈.前缀和.数学计算. 一句话概括思路:在 907. 子数组的最小值之和 中,是对每个 min 乘以管辖范 ...

  4. LeetCode第 227 场周赛题解

    LeetCode第 227 场周赛题解 检查数组是否经排序和轮转得到 原题链接 https://leetcode-cn.com/problems/check-if-array-is-sorted-an ...

  5. LeetCode第187场周赛(Weekly Contest 187)解题报告

    差点又要掉分了,还好最后几分钟的时候,绝杀 AK.干巴爹!!! 第一题:思路 + 模拟暴力. 第二题:线性扫描. 第三题:双指针(滑动窗口) + 优先队列. 第四题:暴力每一行最小 k 个 + 优先队 ...

  6. Leetcode第321场周赛补题

    Leetcode第321场周赛补题 第一题:6245. 找出中枢整数 - 力扣(LeetCode) 分析:由于数组中是差值为1的等差数列,所以可以直接用等差数列求和公式的朴素法更加简便的解决这题,,其 ...

  7. LeetCode 第 194 场周赛

    LeetCode 第 194 场周赛 数组异或操作 思路和代码 保证文件名唯一 思路及代码 避免洪水泛滥 思路及代码 找到最小生成树里的关键边和伪关键边 思路及代码 这次周赛比以往难很多. 数组异或操 ...

  8. Acwing第72场周赛+Leetcode第314场周赛

    Acwing第72场周赛 第一题:AcWing 4624. 最小值 分析:向下取整可以用到math.h头文件中的floor()函数,最后输出时套用两个min()函数求三个数的最小值即可. 代码: #i ...

  9. LeetCode 6077. 巫师的总力量和

    文章目录 一.题目 1.题目描述 2.基础框架 3.原题链接 二.解题报告 1.思路分析 2.时间复杂度 3.代码详解 三.本题小知识 四.加群须知 一.题目 1.题目描述   作为国王的统治者,你有 ...

最新文章

  1. IE6、IE7、IE8、Firefox兼容性CSS
  2. ExtJs 3.1 XmlTreeLoader Example Error
  3. python实现单例模式的几种方式_基于Python中单例模式的几种实现方式及优化详解...
  4. 显示2位小数 python3_Python2和Python3的区别
  5. VINS(五)非线性优化与在线标定调整
  6. 数据科学 IPython 笔记本 7.8 分层索引
  7. 给现有MVC 项目添加 WebAPI
  8. t-SNE原理及代码
  9. mac电脑出现“XXX” is damaged and can’t be opened. You should move it to the Trash
  10. ArcBlock 博客 | 区块链和数据库:致虚极,守静笃
  11. 易支付源码php,「独家修复」2020最新版易支付源码-PHP运营级易支付源码已去后门...
  12. 卡内基梅隆大学计算机博士申请,2020年卡内基梅隆大学博士申请时间
  13. opencv与darknet在python2.7下报错问题
  14. python stacktrace_pystack--python stack trace--让python打印线程栈信息
  15. Geoffrey Hinton
  16. 深度学习中的类别激活热图可视化
  17. 误删excel表格数据都没了怎么恢复
  18. # Python第一节课
  19. 基于Vue移动音乐webapp跨域获取QQ音乐歌单接口
  20. 如何编写makefile

热门文章

  1. Fabric 超级账本学习【8】Hyperledger Fabric 实战——基于区块链的学历学位系统
  2. Java模板设计模式与接口
  3. python实现鼠标手动截图(类似于QQ截图)
  4. 做UI的你,这些平面设计基础知识你了解了吗?
  5. 当代年轻人的生活仪式感有哪些。
  6. 字节跳动面试——C++研发工程师
  7. 北大青鸟 oracle,北大青鸟oracle学习笔记31
  8. realmeq可以用鸿蒙系统吗,realme Q好用吗?realme Q真机上手评测
  9. 峰哥读者一个半月拿到阿里字节拼多多美团offer总结
  10. PDO 大对象 (LOBs)