Codeforces Round #701 (Div. 2) B - Replace and Keep Sorted(简单求和)

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值