Codeforces Round #701 (Div. 2) B - Replace and Keep Sorted(简单求和)
题干
Given a positive integer k, two arrays are called k-similar if:
they are strictly increasing;
they have the same length;
all their elements are positive integers between 1 and k (inclusive);
they differ in exactly one position.
You are given an integer k, a strictly increasing array a and q queries. For each query, you are given two integers li≤ri. Your task is to find how many arrays b exist, such that b is k-similar to array [ali,ali+1…,ari].
Input
The first line contains three integers n, q and k (1≤n,q≤105, n≤k≤109) — the length of array a, the number of queries and number k.
The second line contains n integers a1,a2,…,an (1≤ai≤k). This array is strictly increasing — a1<a2<…<an.
Each of the following q lines contains two integers li, ri (1≤li≤ri≤n).
Output
Print q lines. The i-th of them should contain the answer to the i-th query.
Examples
Input
4 2 5
1 2 4 5
2 3
3 4
Output
4
3
Input
6 5 10
2 4 6 7 8 9
1 4
1 2
3 5
1 6
5 5
Output
8
9
7
6
9
Note
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].
题解
先大概翻译一下题干:
给定一个正整数k,对于任意两个数组,如果满足以下条件则称这两个数组为k似数组:
1.严格递增
2.等长
3.所有元素在[1,k]内
4.两数组恰有一位数字不相等
给定一个正整数k,一个数组a,若干个范围q
对于每个范围,给定两个整数l,r,得到子数组al-ar
任务是找到与子数组k似的数组b的个数
显然我们的任务就是根据给定的子数组,改变子数组中任意一个数字,且保证改变后的数组仍然递增,并统计方法的个数。
我们可以分三类讨论:
1.更改左界上的元素:a[l + 1] - 2种(从1 ~ 左界右侧那个数的范围内都是可选项,不包含右端点)
2.更改右界上的元素:k - a[r - 1] - 1种(从右界左侧那个数 ~ k的范围内都是可选项,不包含左端点)
3.更改中间的数(设为a[i]):对于每个i来说则有a[i] - a[i - 1] - 1 + a[i + 1] - a[i] - 1种(a[i]到左侧那个数,a[i]到右侧那个数的两段范围,不包含端点)
可以注意到i的取值是l+1 ~ r-1,这里我们可以对这个范围求和。先整理上面的式子得到累加项a[i + 1] - a[i - 1] - 2
然后求和,得: a[r] + a[r-1] - a[l] - a[l+1] - 2 * ( r - l - 1)
这里也可以用前缀和来储存第三种修改的次数,这里为了方便,就做求和处理
#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;
typedef long long ll;
int nums[100005];
int main()
{
int n,query,upperBound;
cin>>n>>query>>upperBound;
for(int i = 1 ; i <= n ; ++i){
scanf("%d",nums+i);
}
while(query--){
int l,r;
ll ans = 0;
cin>>l>>r;
ans += nums[l+1] - 2;
ans += nums[r] + nums[r-1] - nums[l] - nums[l+1] - 2 * (r - l - 1);
ans += upperBound - nums[r-1] - 1;
cout<<ans<<endl;
}
return 0;
}