牛客小白月赛86 第三题C数组段数

其实自己是当错题单来看的,哈哈!

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

小蓝获得了一个长度为 n的数组:A1,A2,...,AnA_1,A_2,...,A_nA1​,A2​,...,An​。

小红对小灰灰提出了 mmm 个询问,第 iii 个询问给出两个参数 li,ril_i, r_ili​,ri​ 代表小红截取了原数组的 Ali,Ali+1,...,AriA_{l_i}, A_{l_i + 1}, ..., A_{r_i}Ali​​,Ali​+1​,...,Ari​​ 部分。

对于每个询问,小灰灰想知道小红截取出的数组有多少段。

一个长度为 sss 的数组 B1,B2,...,BsB_1, B_2, ..., B_sB1​,B2​,...,Bs​,其段数被定义为最小的 kkk 使得将数组划分成连续的 kkk 段后,每个元素都属于某一段,且每段数组中的元素种类应该全部相同。

输入描述:

输入第一行包含两个空格分隔的整数 nnn,mmm 分别代表数组长度和询问个数。

接下来一行输入 nnn 个空格分隔的整数分别代表:A1,A2,...,AnA_1, A_2, ..., A_nA1​,A2​,...,An​。

接下来 mmm 行,第 iii 行包含两个空格分隔的整数 li ril_i\ r_ili​ ri​ 代表第 iii 个询问给出的两个参数。

保证:
1≤n,m≤2×1051 \le n,m \le 2\times10^51≤n,m≤2×105 

1≤Ai≤1061 \le A_i \le 10^61≤Ai​≤106 

1≤li≤ri≤n1\le l_i\le r_i\le n1≤li​≤ri​≤n

输出描述:

输出共 m行,第 i 行代表第 i个询问的答案。

示例1

输入

6 4
2 2 3 1 3 3
1 3
2 5
2 2
4 6

输出

2
4
1
2

这个题我当初写的时候是用遍历的方法无脑写的,结果发现超时了,最后去哔哩哔哩牛客官方看完讲解才懂。

题解:这道题的关键点是利用前缀和思想(提前遍历搞好前缀和数组)可以降低时间复杂度。设前缀和数组为s[i],则s[i]=s[i-1]+X,s[i]的数值为从第1个元素到第i个元素的元素之和。

//这个题实打实用到的是前缀和思想
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll a[N],cnt[N];
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	ll n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	for(int i=1;i<=n;i++)
	{
		if(a[i]!=a[i-1])
        {
            cnt[i]=cnt[i-1]+1;
        }
        else
        {
            cnt[i]=cnt[i-1]+0;
        }
	}
	int l,r;
	while(m--)
	{
		cin>>l>>r;
		cout<<(cnt[r]-cnt[l]+1)<<endl;
	}
	return 0;
}
解释:(先看代码)给的序列为2 2 3 1 3 3,上面(s[i]=s[i-1]+X,X根据题而定)我们视两个不同的数之间有一个间隙,我们发现所求的结果恰好就是间隙数(X)+1,在上述代码中我定义全局cnt[i]为前缀和数组来记录1~i个间隙数之和,即对应是0 0 1 2 3 3,那么结果就是cnt[r]-cnt[l]+1.嗯,对,我就是这样理解的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值