[CodeJam 2019 Round 3] Rancake Pyramid(笛卡尔树)

CodeJam 2019 Round 3 Rancake Pyramid

  • problem
  • solution
  • code

problem

神奈子是个很爱打麻将的老婆婆,有一天她把她的麻将放成了 nnn 堆,第 iii 堆的高度为 aia_iai

因为她很喜欢风,所以她用风吹倒了最左边的 LLL 堆麻将和最右边的 RRR 堆麻将,但是她也不想吹倒太多,所以剩下的麻将至少有 333 堆。

因为她很喜欢山,所以她希望剩下的麻将能形成山峰一样的形状。

设剩下的麻将形成的序列为 b1,…,bkb_1,…,b_kb1,,bk,她希望存在至少一个 i∈[1,k]i\in[1,k]i[1,k] 满足 b1≤b2≤...≤bi≥bi+1≥...≥bkb_1\le b_2\le ...\le b_i\ge b_{i+1}\ge ...\ge b_kb1b2...bibi+1...bk

然而她发现很多时候麻将并不是山峰的样子,所以她会为若干堆麻将增高一些高度,她不想花太多时
间,所以她会选择每一堆麻将增高的高度之和最小的方法。

她非常无聊,所以想尝试所有情况,即对于每对满足 0≤L,R≤n,L+R≤n−30\le L,R\le n,L+R\le n-30L,Rn,L+Rn3(L,R)(L,R)(L,R) 都进行一次上述过程。

每次完成一次操作后她都会把麻将还原成初始状态,现在她想知道在全部情况下增加的麻将高度之和是多少,答案可能过大,对 1e9+71e9+71e9+7 取模。

3≤n≤106,1≤ai≤1093\le n\le 10^6,1\le a_i\le 10^93n106,1ai109

solution

有个很重要的结论:对应一段区间操作,一定是选择最高的为山峰,如果有多个相同的随便选一个就行。

证明:这是很显然的。不是很严谨的理解一下。

因为如果最高的不是山峰,那么被选成山峰的点自己都需要被拔高到至少是最高点的高度。

然后被选做山峰的点和最高的点之间的所有点都要被拔高到至少最高点的高度。

显然不如选最高做山峰,然后同样的一段就不需要被拔高到至少最高点的高度。

暴力的 O(n2)O(n^2)O(n2) 我在考场上写出来,结果内存算错了,define int long long MLE 挂了qwq

就是枚举 L,RL,RL,R ,然后得到剩下的还立着的麻将区间 [l,r][l,r][l,r] ,考虑怎么 O(1)O(1)O(1) 计算。

首先要能快速知道区间内的最高点位置 pppst表 预处理即可。

l,rl,rl,r 从最高点分开的左右区间是相同的对称问题,且被最高点分开,相互独立,接下来操作以 lll 为例。

lll 端点作为开始肯定是可以不用改变的,然后判断 l+1l+1l+1lll 的麻将高度,如果 al+1≥ala_{l+1}\ge a_lal+1al 那就不用拔高,否则贪心地只需要拔高到 ala_lal 的高度就行了。这样不仅拔高高度最小化,并且增加了后面不拔高的可能性。

肯定的,不可能每次都扫一遍区间,那是 O(n3)O(n^3)O(n3) 的了。

发现可以通过维护前缀信息来 O(1)O(1)O(1) 计算每个区间对应的答案。

  • preh[i] :表示从 111 开始,iii 最后的高度。

    具体而言:

    • 如果不拔高,即 preh[i−1]≤a[i]preh[i-1]\le a[i]preh[i1]a[i],则 preh[i]=a[i]preh[i]=a[i]preh[i]=a[i]
    • 如果拔高,即 preh[i−1]>a[i]preh[i-1]>a[i]preh[i1]>a[i],则 preh[i]=preh[i−1]preh[i]=preh[i-1]preh[i]=preh[i1]
  • pres[i] :表示从 111 开始维护到 iii 为止一共拔高的高度。

    具体而言:

    • 如果不拔高,则 pres[i]=pres[i−1]pres[i]=pres[i-1]pres[i]=pres[i1]
    • 如果拔高,则 pres[i]=pres[i−1]+preh[i]−a[i]pres[i]=pres[i-1]+preh[i]-a[i]pres[i]=pres[i1]+preh[i]a[i]

每次区间 [l,r][l,r][l,r] 是从 lll 开始的,所以要减去前 l−1l-1l1 个的拔高影响,pres[i]−pres[l−1]pres[i]-pres[l-1]pres[i]pres[l1]

但是注意到,这段区间可能 lll 是被拔高了的,所以要再判断一下然后减去。

具体而言:

  • 如果 a[l]=preh[l]a[l]=preh[l]a[l]=preh[l],证明从 111 开始 lll 是没有被拔高的。

    那么 pres[i]−pres[l−1]pres[i]-pres[l-1]pres[i]pres[l1] 就是 [l,r][l,r][l,r]lll 开始拔高的贡献。

  • 如果 a[i]<preh[l]a[i]<preh[l]a[i]<preh[l],证明从 111 开始 lll 是被拔高过的。

    但是 [l,r][l,r][l,r]lll 开始就不需要拔高,所以 preh[l]−a[l]preh[l]-a[l]preh[l]a[l] 是后面一段多被拔高的高度的。

    要减去,但也不是单独的乘以区间长度,因为有些点不一定被拔高了。

    所以还要维护一个 prec[i]:表示从 111 开始维护到 iii 为止被拔高过的麻将个数。

    减去的应该为:(preh[l]−a[l])(prec[p]−prec[l−1])(preh[l]-a[l])(prec[p]-prec[l-1])(preh[l]a[l])(prec[p]prec[l1])

后缀同理维护,sufh[i] sufs[i] sufc[i]

因为伞兵博主写代码时直接原地覆盖,导致n^2暴力的代码彻底没了。所以就不能提供给大家了┏┛墓┗┓…(((m -__-)m


暴力是抓住左右端点不放。然而一般具有性质的特殊位置,比如最大点位置,一堆区间然后有一个特殊位置等等,正解都是考虑枚举这个特殊位置的。

所以这里考虑枚举每一个麻将做一个区间的最大值的答案。

假设一个麻将 iii 是一段区间 [l,r][l,r][l,r] 的最大值,即 a[l−1],a[r+1]a[l-1],a[r+1]a[l1],a[r+1] 都比 iii 麻将高度高。

那么对于 ∀l≤x≤i≤y≤r,[x,y]\forall\ l\le x\le i\le y\le r,[x,y] lxiyr,[x,y] 都是以 iii 为不变的最高麻将计算。

这样子就是笛卡尔树大根堆的区间限制,考虑左右儿子的贡献,然后再考虑节点本身的贡献。

这里也有正如前面遇到的问题,不同位置开始如果预处理要考虑被多拔高了的高度。

所以不妨一开始就将每个麻将的高度直接剪掉,麻将能在多少种区间内就被减去多少次。

后面直接加上最终高度,这中间的差就是被拔高高度,而且是一一对应的。

具体而言:

建立大根堆笛卡尔树,计算每个点作为最大值的贡献。

记录笛卡尔树上点 iii 的信息 suml,sumrsuml,sumrsuml,sumr 表示 iii 向左 / 右区间内每个点的答案之和,通过儿子快速计算。

跨越 iii 的答案为 suml∗(r−i+1)+sumr∗(i−l+1)suml*(r-i+1)+sumr*(i-l+1)suml(ri+1)+sumr(il+1)

以及 iii 点本身的答案,(i−l+1)∗(r−i+1)∗a[i](i-l+1)*(r-i+1)*a[i](il+1)(ri+1)a[i]

详情可见代码实现。

code

#include <bits/stdc++.h>
using namespace std;
#define maxn 1000005
#define int long long
#define mod 1000000007
int n, ans;
pair < int, int > MS[maxn];
bool vis[maxn];
int a[maxn], s[maxn], L[maxn], R[maxn];void solve( int p ) {vis[p] = 1;int l = p, r = p, suml = 0, sumr = 0;if( vis[p - 1] ) l = L[p - 1], suml = s[p - 1];if( vis[p + 1] ) r = R[p + 1], sumr = s[p + 1];ans = ( ans + ( p - l + 1 ) * sumr ) % mod;ans = ( ans + ( r - p + 1 ) * suml ) % mod;int w = a[p] * ( p - l + 1 ) % mod * ( r - p + 1 ) % mod;ans = ( ans + w ) % mod;L[r] = l, R[l] = r, s[l] = s[r] = ( suml + sumr + w ) % mod;
}signed main() {scanf( "%lld", &n );for( int i = 1;i <= n;i ++ ) {scanf( "%lld", &a[i] );ans = ( ans - i * ( n - i + 1 ) % mod * a[i] ) % mod;MS[i] = { a[i], i };}sort( MS + 1, MS+ n + 1 );for( int i = 1;i <= n;i ++ ) solve( MS[i].second );printf( "%lld\n", ( ans + mod ) % mod );return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316693.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Harbour.Space Scholarship Contest 2021-2022 (open for everyone, rated, Div. 1 + Div. 2)

Harbour.Space Scholarship Contest 2021-2022 (open for everyone, rated, Div. 1 Div. 2) 题号题目知识点ADigits Sum签到BReverse String思维CPenalty思维DBackspace逆向思维EPermutation Shift置换群FPairwise ModuloGCommon Divisor GraphHXOR and DistanceIStairs cf15…

模板:全局平衡二叉树

所谓全局平衡二叉树&#xff0c;就是在全局来看都很平衡的二叉树。 &#xff08;逃 前言 这个引言倒是实话&#xff08;雾 可以把一些本来只能用树剖两个 log 做的问题在单log 时间复杂度解决。 修改通常来说只能支持单点修改。 查询解决链上问题或者全局问题更为方便&#x…

[CodeJam 2021 Round 3] Square Free(调整法 / 字典序最小解网络流)

CodeJam 2021 Round3 Square Freeproblemsolutioncodecode-stdproblem 神奈子是个很爱打麻将的老婆婆&#xff0c;有一天她把她的麻将放进了一个 nmn\times mnm 的网格图里&#xff0c;每个麻将可以左斜着放入网格中&#xff08;如 / &#xff09;&#xff0c;也可以右斜着&am…

P6773 [NOI2020] 命运(dp、线段树合并)

前言 一道看起来很毒瘤但其实还算小清新的题&#xff1f; 理解后感觉其实并没有那么难。 暴力分非常足&#xff0c;好评。 奇妙的线段树合并技巧增加了。 解析 解法1 你是怎么手玩的样例一&#xff1f; 大部分&#xff08;比如我&#xff09;都是容斥吧。 把手玩的方法搬到…

ConsurrentDictionary并发字典知多少?

在上一篇文章你真的了解字典吗?一文中我介绍了Hash Function和字典的工作的基本原理.有网友在文章底部评论,说我的Remove和Add方法没有考虑线程安全问题.https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2?redirectedfromMSDN&viewn…

[luogu 4292][bzoj 1758][WC2010] 重建计划(点分治 + dp + 单调队列优化 + 启发式合并)

[WC2010]重建计划problemsolutioncodeproblem 洛谷指路 solution 一看那个道路平均价值的式子&#xff1a;AvgValue∑e∈Sv(e)∣S∣\text{AvgValue}\frac{\sum_{e\in S}v(e)}{|S|}AvgValue∣S∣∑e∈S​v(e)​ 就是 0/1分数规划 的样子。 所以考虑二分最终的答案 midmidmid…

cf1553C. Penalty

cf1553C. Penalty 题意&#xff1a; 有十轮点球&#xff0c;两个队伍轮流进行&#xff0c;1表示进&#xff0c;0表示不进&#xff0c;&#xff1f;表示未知&#xff0c;如果比赛没有了悬念将直接结束。现在让你预测一个情况&#xff0c;使得进行的轮数最少。裁判在决定停止点…

ASP.NET Core 基于JWT的认证(二)

上一节我们对 Jwt 的一些基础知识进行了一个简单的介绍&#xff0c;这一节我们将详细的讲解,本次我们将详细的介绍一下 Jwt在 .Net Core 上的实际运用。.Net Core 2.2Visual Studio 2017ASP.NET Core WebAPI2在上一篇文章中&#xff0c;我们详细的介绍了JWT的知识&#xff0c;这…

P6774 [NOI2020] 时代的眼泪(分块)

前言 看到题目名&#xff1a;别骂了别骂了。 一道很中规中矩的YNOI吧。 卡在整块对整块的贡献上了。 这也确实算是本题最不好做的部分了。 前置知识&#xff1a;Yuno loves sqrt technology I 解析 区间逆序对加强版&#xff1f;很难不想到两道 YLST。 然而多了两维限制&a…

[NOIP2021] 数列(计数dp)

solution f[i][j][k][num][p]:2pf[i][j][k][num][p]:2^pf[i][j][k][num][p]:2p 选择了 iii 个&#xff0c;前 p−1p-1p−1 位 (202p−1)(2^0~2^{p-1})(20 2p−1) 已经选了jjj个&#xff0c;低位向高位进位上来 kkk&#xff0c;前 ppp 位已经确定有 numnumnum 个位置为 111&…

Xor sum HDU - 6955

Xor sum HDU - 6955 题意&#xff1a; 给定一个长度为n的整数序列&#xff0c;求其XOR和不小于k的最短连续子序列。 如果有多个相同长度的连续子序列&#xff0c;则打印具有最小左端点的连续子序列。 如果没有连续的子序列开关XOR总和不小于k&#xff0c;只需打印“-1”。 …

模板:子序列自动机(字符串)

所谓子序列自动机&#xff0c;就是根据子序列建立的自动机。 &#xff08;逃&#xff09; 前言 小清新算法。 解析 和其他自动机类似的&#xff0c;我们希望子序列自动机能且只能接受原串的所有子序列。 考虑一个问题&#xff1a;给你一个串 T&#xff0c;如何判断它是否是…

Docker最全教程之Go实战,墙裂推荐(十九)

前言与其他语言相比&#xff0c;Go非常值得推荐和学习&#xff0c;真香&#xff01;为什么&#xff1f;主要是可以直接编译成机器代码&#xff08;性能优越&#xff0c;体积非常小&#xff0c;可达10来M&#xff0c;见实践教程图片&#xff09;而且设计良好&#xff0c;上手门槛…

[BZOJ3093][Fdu校赛2012] A Famous Game(不等概率)

problem BOZJ3093 solution 逆概率公式&#xff0c;即贝叶斯(Bayes)公式&#xff1a; 假设 B1,B2,...,BnB_1,B_2,...,B_nB1​,B2​,...,Bn​ 是 Ω\OmegaΩ 的一个分割&#xff0c;P(A)>0P(A)>0P(A)>0&#xff0c;则有 P(Bk∣A)P(ABk)P(A)P(Bk)P(A∣Bk)∑i1nP(Bi)…

Mod, Or and Everything HDU - 6950

Mod, Or and Everything HDU - 6950 题意&#xff1a; 给你一个n,问(n%1) or (n%2) or … or (n %n)的值 题解&#xff1a; 无论n为奇偶&#xff0c;定义m(n-1)/2&#xff0c; 我们发现n mod i<m&#xff0c;而当i<m时&#xff0c;有n mod (n-i) i ,于是就有n mod i …

你注意到 .Net Framework 和 .Net Core 中使用 Session 的区别了吗?

在测试一个例子时发现的问题&#xff0c;这个示例实现的功能是刷新页面也能保持表格锁定列的状态&#xff0c;先看下页面的完成效果&#xff1a;测试中发现&#xff0c;几乎相同的代码&#xff1a;在 FineUIMvc&#xff08;Net Framework&#xff09;下没有问题&#xff1a;htt…

模板:拉格朗日乘子法(数学)

所谓拉格朗日乘子法&#xff0c;就是拉格朗日发明的乘子法。 &#xff08;逃&#xff09; 前言 曾经&#xff0c;我被它爆杀&#xff1b;如今&#xff0c;不同的日子&#xff0c;同样的题目&#xff0c;我却不再是曾经的我了。 因为我写模拟退火了。 也不能老是这么混着&…

[UOJ299][CTSC2017] 游戏

【CTSC2017】游戏 problem UOJ299 solution 定义 Xi:X_i:Xi​: 当前已知条件第 iii 局的状态 1/01/01/0&#xff08;胜/败&#xff09;。 将 XiCiX_iC_iXi​Ci​ 记为事件 AiA_iAi​。 假设现在已知条件共有 sss 个&#xff0c;即&#xff1a;第 k1∼sk_{1\sim s}k1∼s​…

Alice and Bob

Alice and Bob 题意&#xff1a; 两人博弈&#xff0c;每次一个人从一堆中拿k个&#xff0c;同时从另一堆拿k * s(s>0)个&#xff0c;问谁先不能拿 10000组数据,N<5000 题解&#xff1a; (x,y)表示第一堆石头数量为x&#xff0c;第二堆为y 如果(x,y)是必败状态&#…

一键发布部署vs插件[AntDeploy]开源了

deploy to remote server by one button click功能支持docker一键部署(支持netcore)支持iis一键部署(支持netcore和framework)(支持增量发布)(支持一键回滚)(支持点火)支持windows服务一键部署(支持netcore和framework)(支持增量发布)(支持一键回滚) 使用插件前我要发布一个net…