序列查询新解(第24次CCF - B)(双指针)

传送门

题目

在这里插入图片描述

思路

双指针。
分别分析   f ( x ) 和 g ( x )   ~f(x) 和 g(x)~  f(x)g(x) 的性质

  • 对 于 f ( x ) 对于f(x) f(x)
    可 以 将 序 列 a 看 作 n 个 不 相 重 叠 且 连 续 的 区 间 。 第 i 个 区 间 为   [   a [ i ] ,    a [ i + 1 ]   ) 第 i 个 区 间 中 所 有 的 数 的 函 数 值 f ( x ) = i 可以将序列a看作n个不相重叠且连续的区间。第i个区间为~[~a[i], ~~a[i + 1]~)\\ 第i个区间中所有的数的函数值f(x) =\bm{i} ani [ a[i],  a[i+1] )if(x)=i
  • 对 于 g ( x ) 对于g(x) g(x)
    定 义 : b [ i ] = i × r , 且 b [ i ] < = m 定义: b[i] = i \times r, 且b[i] <= m b[i]=i×r,b[i]<=m
    b [ 0 ] = 0 b [ 1 ] = r b [ 2 ] = 2 r ⋯ ⋯ b [ k − 1 ] = ( k − 1 ) r b [ k ] = m b[0] = 0\\b[1] = r\\b[2] = 2r\\\cdots\cdots\\b[k - 1] = (k - 1)r\\b[k] = m b[0]=0b[1]=rb[2]=2rb[k1]=(k1)rb[k]=m
    同 理 , b 序 列 也 可 以 看 作 k 个 不 同 的 区 间 第 j 个 区 间 对 应 的 函 数 值 g ( x ) = j 同理,b序列也可以看作k个不同的区间\\第j个区间对应的函数值g(x) = \bm{j} bkjg(x)=j

每次移动时,将当前指针的公共部分累加入ans中即可。具体细节看代码部分
在这里插入图片描述
第 一 次 求 得 [ 0 , a [ i ] ) 的 贡 献 第一次求得[0, a[i])的贡献 [0,a[i])
第 二 次 求 得 [ a [ 1 ] , b [ 1 ] ) 的 贡 献 第二次求得[a[1], b[1])的贡献 [a[1],b[1])
第 三 次 求 得 [ b [ 1 ] , a [ 2 ] ) 的 贡 献 第三次求得[b[1], a[2])的贡献 [b[1],a[2])
⋯ ⋯ \cdots\cdots
最 终 i , j 两 个 指 针 均 指 向 两 个 数 组 各 自 的 末 尾 ( a [ n + 1 ] 与 b [ k ] ) \\最终i,j两个指针均指向两个数组各自的末尾(a[n + 1]与b[k]) ij(a[n+1]b[k])

CODE

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 7;
ll a[N], b[N];

int main()
{
	IOS;
	ll n, m; cin >> n >> m;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	a[n + 1] = m;

	ll r = m / (n + 1);
	ll k = 1;
	for (; k * r < m; k++)
		b[k] = k * r;
	b[k] = m;

	ll ans = 0;
	int i = 1, j = 1;
	while (i < n + 1 || j < k)//注意是“或”
	{
		if (a[i] < b[j])
		{
			ans += (min(a[i + 1], b[j]) - a[i]) * abs(j - 1 - i);
			i++;
		}
		else if (a[i] > b[j])
		{
			ans += (min(a[i], b[j + 1]) - b[j]) * abs(i - 1 - j);
			j++;
		}
		else
		{
			ans += (ll)(min(a[i + 1], b[j + 1]) - a[i]) * abs(i - j);
			i++;
			j++;
		}
	}

	cout << ans << endl;

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

to cling

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值