CodeForces - 862E 二分+错位求和技巧

博客讲述了如何解决CodeForces上的862E问题,该问题涉及到对数组的更新操作和求最小函数值。通过解析题目和解题思路,博主指出在更新数组时,根据更新数量的奇偶性和起始位置,可以推导出函数值的变化。利用二分查找优化算法,寻找每次更新后的最小函数值。最后,博主提供了AC(Accepted)代码作为解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

题目大意:给一个长度为n的数组a, 和一个长度为m的数组b,和更新次数q; 函数f(j)的意思是   , 求出最小的函数值,然后会有q次更新数组a, 每次更新一个区间,从l到r之间每个值加x。输出每次更新之后所有f的最小值。

解题思路:我们可以通过技巧获得没更新之前的每个函数值,具体看代码。我们看公式可以看出一个规律,我们更新数组a时,如果更新的个数是偶数,等于没更新(数组a的系数正负1交替出现,每两项x就会抵消),如果是奇数,并且是从奇数开始的(l为奇数),那么就是f加上x, 如果l时偶数,那就减去x。(因为偶数的系数时-1,那么最后一个没抵消的那个数的系数也是-1)。每次更新都是将所有的f加上或者减去x,因此我们没必要每次都更新,我们只需保存下来就可以,保存到一个值中cur中的话,那么我们只需找到所有f中与cur相差最小的那个数即可.(函数是绝对值)。用二分查找即可。


AC代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

int n, m, q;
long long F[100000];
long long B[100050];

long long lower_find(long long x)
{
	int L =0, R = m-n;
	while(R > L)
	{
		int mid = (R+L+1)/2;
		if(F[mid] ==  x) return 0;
		else if(F[mid] > x) R = mid-1;
		else L = mid;
	}
	long long x1, x2;
	x1 = abs(F[L]-x);
	if(L < m-n)
		x2 = abs(F[L+1]-x);
	else x2 =  9223372036854775807; 
	return x1 < x2? x1 : x2;
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	long long f = 1, a, b;
	long long suma = 0,sumb = 0;
	for(int i=1; i<=n; i++)
	{
		scanf("%lld", &a);
		suma += f*a;
		f = -f;
	}
	f = -1;
	for(int i=1; i<=m; i++)
	{
		scanf("%lld", &B[i]);
		sumb += B[i] * f;
		f = -f;
		if(i>=n)
		{
			int t = (i-n)%2 ? -1 : 1;
			F[i-n] = suma +  sumb * t;
			sumb += B[i-n+1] * t;
		}
	}
	sort(F, F+m-n+1);
	int l, r;
	long long x, cur = 0;
	printf("%lld\n", lower_find(0));
	for(int i=0; i<q; i++)
	{
		scanf("%d%d%lld", &l, &r, &x);
		if((r-l)%2 == 0)
			if(l%2 == 1) cur += x;
			else cur -= x;
		printf("%lld\n", lower_find(-cur));
	}
		
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值