CCF-CSP 202112-2 序列查询新解【子区间】

本文介绍了一种使用尺取法的算法,通过固定区间并遍历其中的子区间,确保子区间内f(i)和g(i)值的同一性,从而高效地计算它们的差值。核心思路是利用g(i)的取值规律和区间终点计算,实现了区间内相同值的快速匹配。给出的C++代码展示了如何应用此技巧解决实际问题。
摘要由CSDN通过智能技术生成

题目链接

http://118.190.20.162/view.page?gpid=T137

思路

有点类似尺取法枚举区间。这题是先固定一个区间,再在这个区间内遍历子区间。

遍历 f ( i ) f(i) f(i)值相同的区间,假设每个区间范围[L, R],再在[L, R]内遍历 g ( i ) g(i) g(i)值相同的子区间,这样在计算时就能保证子区间的 f ( i ) f(i) f(i)值全部相同、 g ( i ) g(i) g(i)值全部相同。比较关键的地方是要找到 g ( i ) g(i) g(i)及其区间右端点的两个对应关系:
g ( i ) = i / r g(i)=i/r g(i)=i/r

g ( i ) _ e n d p o s = [ g ( i ) + 1 ] ∗ r − 1 g(i)\_endpos=[g(i)+1]*r-1 g(i)_endpos=[g(i)+1]r1
g ( i ) _ e n d p o s g(i)\_endpos g(i)_endpos表示取值为 g ( i ) g(i) g(i)的区间的右端点位置。

AC代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int n,N,a[maxn];
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>N;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	a[0]=0; a[n+1]=N;
	int r=N/(n+1);
	ll ans=0;
	for(int i=0;i<=n;i++){
		int L=a[i];
		int R=a[i+1]-1;
		// 当前区间[L,R]
		int fi=i; // [L,R]区间内f(i)值相同,均为fi
		// 接下来在[L,R]区间内遍历g(i)的各个区间
		// 每次保证遍历的子区间内的g(i)值相同
		int startpos=L;
		while(startpos<=R){
			int gi=startpos/r; // g(i)值
			int endpos=min((gi+1)*r-1,R); // g(i)值相同的最后一个位置,注意不要超过R
			// [startpos,endpos]区间内的g(i)值相同,均为gi
			// [startpos,endpos]是[L,R]的子区间,保证fi相同,gi相同,直接计算即可
			ans+=abs(fi-gi)*(endpos-startpos+1);
			startpos=endpos+1;
		}
	}
	printf("%lld\n",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

nefu-ljw

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

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

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

打赏作者

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

抵扣说明:

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

余额充值