【差分】luogu_P4231 三步必杀

题意

对一个数组的某个区间加上一段等差数列,求出若干个操作后每个元素的值。

思路

考虑差分。
A A A为原数组, B B B为一阶差分数组, C C C为二阶差分数组。
[ l , r ] [l,r] [l,r]加上首项为 s s s,末项为 e e e,公差为 d d d的等差数列,可得
A i = A i + s + ( i − l ) ∗ d A_i=A_i+s+(i-l)*d Ai=Ai+s+(il)d

B l = ( A l + s ) − A l − 1 = B l + s B_l=(A_l+s)-A_{l-1}=B_l+s Bl=(Al+s)Al1=Bl+s
B i = ( A i + s ∗ ( i − l ) ∗ d ) − ( A i − 1 + s ∗ ( i − 1 − l ) ∗ d ) = B i + d B_i=(A_i+s*(i-l)*d)-(A_{i-1}+s*(i-1-l)*d)=B_i+d Bi=(Ai+s(il)d)(Ai1+s(i1l)d)=Bi+d
B r + 1 = A r + 1 − ( A r + e ) = B r + 1 − e B_{r+1}=A_{r+1}-(A_r+e)=B_{r+1}-e Br+1=Ar+1(Ar+e)=Br+1e

C l = ( B l + s ) − ( B l − 1 ) = C l + s C_l=(B_l+s)-(B_{l-1})=C_l+s Cl=(Bl+s)(Bl1)=Cl+s
C l + 1 = ( B l + 1 + d ) − ( B l + s ) = C l + d − s C_{l+1}=(B_{l+1}+d)-(B_l+s)=C_l+d-s Cl+1=(Bl+1+d)(Bl+s)=Cl+ds
C r + 1 = ( B r + 1 − e ) − ( B r + d ) = C l − d − e C_{r+1}=(B_{r+1}-e)-(B_r+d)=C_l-d-e Cr+1=(Br+1e)(Br+d)=Clde
C r + 2 = B r + 2 − ( B r + 1 − e ) = C r + 2 + e C_{r+2}=B_{r+2}-(B_{r+1}-e)=C_{r+2}+e Cr+2=Br+2(Br+1e)=Cr+2+e

故只用修改4个值,做两次前缀和即可。

代码

#include <cstdio>
#include <algorithm>
#define int long long

const int N = 1e7 + 5;
int n, m, ans1, ans2;
int a[N];

signed main() {
	scanf("%lld %lld", &n, &m);
	for (int i = 1, l, r, s, e; i <= m; i++) {
		scanf("%lld %lld %lld %lld", &l, &r, &s, &e);
		int d = (e - s) / (r - l);
		a[l] += s;
		a[l + 1] += d - s;
		a[r + 1] -= d + e;
		a[r + 2] += e;
	}
	for (int i = 1; i <= n; i++)
		a[i] += a[i - 1];
	for (int i = 1; i <= n; i++)
		a[i] += a[i - 1], ans1 ^= a[i], ans2 = std::max(ans2, a[i]);
	printf("%lld %lld", ans1, ans2);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值