[CF935F]Fafa and Array

法法round(雾

题意:给一个序列$a_{1\cdots n}$,定义$\begin{align*}f=\sum\limits_{i=1}^{n-1}\left|a_i-a_{i+1}\right|\end{align*}$,修改是区间加,询问$(l,r,x)$表示把某个$a_i(i\in[l,r])$加上$x$后最大的$f$是多少

先考虑把某个$a_i$加上$x$后对$f$的影响,不失一般性,我们假设$a_{i-1}\leq a_{i+1}$,那么对$a_i$的大小分类讨论,有三种情况

①$a_i\leq a_{i-1},a_i\leq a_{i+1}$,我们不希望找到这样的位置,因为$f$有可能变小,实际上当$l\neq r$时$a_{l\cdots r}$不会全是这种情况(所有$a_i$都比它两边的元素小,矛盾),所以直接忽略即可(当$l=r$时还是要特殊处理的)

②$a_{i-1}\leq a_i\leq a_{i+1}$,$f$可能变大,变化量为$2(x+a_i-a_{i+1})$

③$a_i\geq a_{i+1},a_i\geq a_{i-1}$,$f$一定会变大,变化量为$2x$

所以我们先把原序列差分:$d_i=a_i-a_{i-1}$,然后在线段树的下标为$i$的位置存$\min(d_i,0)+\min(-d_{i+1},0)$,每次查询$[l,r]$的最大值$mx$,那么$\max(0,2(x+mx))$就是$f$的增量

取$\min$对应着③,如果没有③,我们找到的是最小的$|a_i-\max(a_{i-1},a_{i+1})|$,这使得$f$增量最大,最后还要和$0$取$\max$是因为$f$可能不变(即这个区间任何一个数加上$x$都不会变成③)

因为做了差分,所以区间修改就变成单点修改了,修改$d_l,d_{r+1}$和线段树中的$l-1,l,r,r+1$即可

#include<stdio.h>
typedef long long ll;
const ll inf=9223372036854775807ll;
ll max(ll a,ll b){return a>b?a:b;}
ll min(ll a,ll b){return a<b?a:b;}
ll abs(ll x){return x>0?x:-x;}
ll d[300010],mx[1200010];
int M;
ll num(int i){
	return min(d[i],0)+min(-d[i+1],0);
}
void pushup(int x){mx[x]=max(mx[x<<1],mx[x<<1|1]);}
ll query(int s,int t){
	ll res=-inf;
	for(s+=M-1,t+=M+1;s^t^1;s>>=1,t>>=1){
		if(~s&1)res=max(res,mx[s^1]);
		if(t&1)res=max(res,mx[t^1]);
	}
	return res;
}
void modify(int x){
	mx[x+M]=num(x);
	for(x=(x+M)>>1;x;x>>=1)pushup(x);
}
int main(){
	int n,m,i,op,l,r,x;
	ll sum;
	scanf("%d",&n);
	for(M=1;M<n;M<<=1);
	for(i=1;i<=n;i++)scanf("%I64d",d+i);
	for(i=n;i>0;i--)d[i]-=d[i-1];
	d[1]=0;
	sum=0;
	for(i=2;i<=n;i++)sum+=abs(d[i]);
	for(i=M;i<M<<1;i++)mx[i]=-inf;
	for(i=1;i<=n;i++)mx[i+M]=num(i);
	for(i=M-1;i>0;i--)pushup(i);
	scanf("%d",&m);
	while(m--){
		scanf("%d%d%d%d",&op,&l,&r,&x);
		if(op==1){
			if(l==r)
				printf("%I64d\n",sum-abs(d[l])+abs(d[l]+x)-abs(d[l+1])+abs(d[l+1]-x));
			else
				printf("%I64d\n",sum+max(0,2*(x+query(l,r))));
		}else{
			if(l>1)sum-=abs(d[l]);
			d[l]+=x;
			if(l>1)sum+=abs(d[l]);
			modify(l);
			if(l>1)modify(l-1);
			if(r<n){
				sum-=abs(d[r+1]);
				d[r+1]-=x;
				sum+=abs(d[r+1]);
				modify(r+1);
				modify(r);
			}
		}
	}
}

转载于:https://www.cnblogs.com/jefflyy/p/8818422.html

python023基于Python旅游景点推荐系统带vue前后端分离毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值