[Codeforces Global Round 2] D. Frets On Fire (二分)

本文介绍了一种解决特定区间并集问题的有效算法。通过排序和二分查找技巧,该算法可以快速计算出给定数组经过特定操作后产生的不同数值的数量。适用于处理大量查询的情况。

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

D. Frets On Fire

题意:

  给你一个长度为 n n n的数组,有 q q q次询问,每次询问包含一个 l l l r r r,求原数组中每个元素加上 k k k ( k ∈ [ l , r ] ) (k\in[l, r]) (k[l,r])能形成多少个不同的数。
如:原数组为 3 1 4 1 5 9时, F r e t Fret Fret 0 0 0 2 2 2产生的 s i + F r e t s_i + Fret si+Fret 为:

Fret012
s 1 s_1 s1345
s 2 s_2 s2123
s 3 s_3 s3456
s 4 s_4 s4123
s 5 s_5 s5567
s 6 s_6 s691011

不同的数为 1,2,3,4,5,6,7,9,10,11 共10个。

题目分析:

  对于每一个询问的答案很明显与 l l l r r r 无关而与区间的长度 m = r − l + 1 m=r-l+1 m=rl+1有关。如果把原数组中的数看成区间的起点,区间的长度为 m m m,那么问题就转换成了求多个区间并集的区间长度。将原数组排序,建立新的数组 d d d,其中 d i = s i + 1 − s i d_{i} = s_{i+1} - s_{i} di=si+1si 。如果 d i d_{i} di小于 m m m说明区间被合并, d i d_{i} di大于 m m m说明区间为独立区间,二分一下求和就好了。

代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100005;

ll s[maxn];
ll d[maxn];
ll sd[maxn];
int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%I64d", &s[i]);
	sort(s + 1, s + 1 + n);
	for (int i = 1; i < n; i++) d[i] = s[i + 1] - s[i];
	sort(d + 1, d + n);
	for (int i = 1; i < n; i++) sd[i] += sd[i - 1] + d[i];
	int q;
	scanf("%d", &q);
	while (q--) {
		ll l, r;
		scanf("%I64d %I64d", &l, &r);
		ll m = r - l + 1;
		int pos = lower_bound(d + 1, d + n, m) - d - 1;
		ll ans = (n - pos)*m + sd[pos];
		printf("%I64d ", ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值