CF1485B Replace and Keep Sorted

文章讲述了如何在给定一个严格递增的整数数组A和查询区间[L_i,R_i]的情况下,计算有多少个与数组A在指定位置k相似的严格递增数组。关键在于使用差分和的思想来避免重复计数并解决超时问题。

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

Replace and Keep Sorted

题目描述

Given a positive integer kkk , two arrays are called kkk -similar if:

  • they are strictly increasing;
  • they have the same length;
  • all their elements are positive integers between 111 and kkk (inclusive);
  • they differ in exactly one position.

You are given an integer kkk , a strictly increasing array aaa and qqq queries. For each query, you are given two integers li≤ril_i \leq r_iliri . Your task is to find how many arrays $ b $ exist, such that bbb is kkk -similar to array [ali,ali+1…,ari][a_{l_i},a_{l_i+1}\ldots,a_{r_i}][ali,ali+1,ari] .

输入格式

The first line contains three integers nnn , qqq and kkk ( 1≤n,q≤1051\leq n, q \leq 10^51n,q105 , $n\leq k \leq 10^9 $ ) — the length of array aaa , the number of queries and number kkk .

The second line contains nnn integers a1,a2,…,ana_1, a_2, \ldots,a_na1,a2,,an ( 1≤ai≤k1 \leq a_i \leq k1aik ). This array is strictly increasing — a1<a2<…<ana_1 < a_2 < \ldots < a_na1<a2<<an .

Each of the following $ q $ lines contains two integers lil_ili , rir_iri ( 1≤li≤ri≤n1 \leq l_i \leq r_i \leq n1lirin ).

输出格式

Print qqq lines. The iii -th of them should contain the answer to the iii -th query.

样例 #1

样例输入 #1

4 2 5
1 2 4 5
2 3
3 4

样例输出 #1

4
3

样例 #2

样例输入 #2

6 5 10
2 4 6 7 8 9
1 4
1 2
3 5
1 6
5 5

样例输出 #2

8
9
7
6
9

提示

In the first example:

In the first query there are $ 4 $ arrays that are $ 5 $ -similar to $ [2,4] $ : $ [1,4],[3,4],[2,3],[2,5] $ .

In the second query there are $ 3 $ arrays that are $ 5 $ -similar to $ [4,5] $ : $ [1,5],[2,5],[3,5] $ .

题面翻译

给定一个自然数 kkk

我们定义两个数列是 kkk 相同的,当且仅当这两个数列长度相同,严格递增,元素都在 [1,k][1,k][1,k] 之间,且恰好存在一个数不同。

现在给出一个长度为 nnn 的严格递增的数列 AAA ,每次询问一个区间 [Li,Ri][L_i,R_i][Li,Ri] ,求出ALi,ALi+1……ARiA_{L_i},A_{L_i+1}……A_{R_i}ALi,ALi+1……ARi 这个数列有多少个与其 kkk 相同的数列。

思路:

每次只能变动原序列一个元素,且这个元素变动范围在其前后两元素之间。

位于开头的元素需要 ≥1\ge 11,位于末尾的元素需要 ≤k\le kk,其余中间的元素 aia_iai 需要 ai−1a_{i-1}ai1 小于 aia_iai 小于 ai+1a_{i+1}ai+1

所以利用差分和,设差分为 d[i]=a[i]-a[i-1],则每个元素(非首尾元素)可以有 d[i]-1+d[i+1]-1种可行情况
临界分析:对于首尾元素,a[1]d[1]-1+a[1]-1种可行情况,a[n]d[n]-1+k-a[n]种可行情况。

把所有可行情况加起来就可以了,算 sumsumsum 的时候用到差分和,避免重复计算超时。


代码:

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<list>
using namespace std;
const int N = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e6;
#define LL long long

int a[N] , n , t , k , num[N];

int main(){
	cin >> n >> t >> k;
	for(int i = 1 ; i <= n ; i++){
		cin >> a[i];
	}
	a[0] =0 , a[n + 1] = k;
	for(int i = 1 ; i <= n ; i++){
		num[i] = (a[i] - 1 - a[i - 1]) + (a[i + 1] - a[i] - 1);
	}
	for(int i = 1 ; i <= n ; i++){
		num[i] += num[i - 1];
	}
	while(t--){
		int l , r;
		cin >> l >> r;
		LL ans;
		if(l == r){
			ans = k - 1;
		}else {
			ans= num[r - 1] - num[l];
			ans += a[l + 1] - 2 + k - 1 - a[r - 1];
		}
		cout << ans << endl;
	}
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值