ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P7482 不条理狂诗曲 题解

2021-08-22 12:01:42  阅读:178  来源: 互联网

标签:md P7482 int 题解 read 狂诗 gl fl dp


Luogu

Description.

给定一个序列 \(\{a_i\}\),定义 \(f(l,r)\) 表示 \([l,r]\) 中取出一些不相邻数的最大和。
求 \(\sum_{l=1}^n\sum_{r=l}^nf(l,r)\)。

Solution.

分治,拆贡献,然后接下来需要考虑跨过 \(l\le md,r>md\) 的 \(f(l,r)\) 贡献。
左右两边除了选中点之外互不干扰,我们考虑直接 dp 的合并。
先左边做一遍 dp,右边做一遍 dp,设 \(f_l(i),g_l(i),f_r(i),g_r(i)\) 表示从 \(md/md+1\) dp 到 \(i\),\(md/md+1\) 选或不选的最大和。
答案 \(f(a,b)\) 就是 \(\max(f_l(a)+g_r(b),g_l(a)+f_r(b))\)。
考虑决策,若 \(f_l(a)+g_r(b)<g_l(a)+f_r(b)\),则有 \(f_r(b)-g_r(b)>f_l(a)-g_l(a)\)
然后直接左边按照 \(f_l(a)-g_l(b)\) 排序,就能找到决策点。
然后维护一下 \(f_l(x)\) 的前缀和和 \(g_l(x)\) 的后缀和即可。

Coding.

点击查看代码
//是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
template<typename T>inline void read(T &x)
{
	x=0;char c=getchar(),f=0;
	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	f?x=-x:x;
}
template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}/*}}}*/
const int N=100005,P=1e9+7;int n,a[N],id[N],rs;
ll fl[N],gl[N],fr[N],gr[N],sf[N],sg[N];
struct ${ll f,g;char operator<($ b) const {return f-g<b.f-b.g;}}F[N];
inline void solve(int l,int r)
{
	int md=(l+r)>>1;if(l==r) return (rs+=a[l])%=P,void();else solve(l,md),solve(md+1,r);
	fl[md+1]=0,fl[md]=a[md];for(int i=md-1;i>=l;i--) fl[i]=max(fl[i+1],fl[i+2]+a[i]);
	gl[md]=0,gl[md-1]=a[md-1];for(int i=md-2;i>=l;i--) gl[i]=max(gl[i+1],gl[i+2]+a[i]);
	fr[md]=0,fr[md+1]=a[md+1];for(int i=md+2;i<=r;i++) fr[i]=max(fr[i-1],fr[i-2]+a[i]);
	gr[md+1]=0,gr[md+2]=a[md+2];for(int i=md+3;i<=r;i++) gr[i]=max(gr[i-1],gr[i-2]+a[i]);
	int tt=0;for(int i=l;i<=md;i++) F[++tt]=($){fl[i],gl[i]};
	sort(F+1,F+tt+1);for(int i=1;i<=tt;i++) sf[i]=sf[i-1]+F[i].f,sg[i]=sg[i-1]+F[i].g;
	//printf("%d %d %d : %d\n",l,md,r,rs);
	//if(l==1&&md==2&&r==3) for(int i=1;i<=tt;i++) printf("ll %lld %lld\n",F[i].f,F[i].g);
	for(int i=md+1;i<=r;i++)
	{
		int wh=lower_bound(F+1,F+tt+1,($){fr[i],gr[i]})-F-1;
		//if(l==1&&md==2&&r==3) printf("rr %lld %lld\n",fr[i],gr[i]);
		rs=(rs+(sf[tt]-sf[wh])+gr[i]%P*(tt-wh))%P;
		rs=(rs+sg[wh]+fr[i]%P*wh)%P;
	}
	//printf("%d %d %d : %d\n",l,md,r,rs);
}
int main()
{
	read(n);for(int i=1;i<=n;i++) read(a[i]);
	return solve(1,n),printf("%d\n",rs),0;
}

标签:md,P7482,int,题解,read,狂诗,gl,fl,dp
来源: https://www.cnblogs.com/pealfrog/p/15171835.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有