先 按 照 s i 从 小 到 大 排 序 先按照s_i从小到大排序 先按照si从小到大排序
设 第 一 个 区 间 是 [ s 1 + l , s 1 + r ] , 那 么 对 答 案 贡 献 是 r − l + 1 设第一个区间是[s_1+l,s_1+r],那么对答案贡献是r-l+1 设第一个区间是[s1+l,s1+r],那么对答案贡献是r−l+1
考 虑 第 二 个 区 间 [ s 2 + l , s 2 + r ] , 那 么 对 答 案 是 多 少 ? 考虑第二个区间[s_2+l,s_2+r],那么对答案是多少? 考虑第二个区间[s2+l,s2+r],那么对答案是多少?
显 然 当 s 2 + l > s 1 + r 时 , 对 答 案 贡 献 是 r − l + 1 , 也 就 是 和 上 一 个 区 间 不 重 叠 显然当s_2+l>s1+r时,对答案贡献是r-l+1,也就是和上一个区间不重叠 显然当s2+l>s1+r时,对答案贡献是r−l+1,也就是和上一个区间不重叠
否 则 重 叠 , 对 答 案 贡 献 是 s 2 − s 1 否则重叠,对答案贡献是s2-s1 否则重叠,对答案贡献是s2−s1
所 以 每 个 区 间 对 答 案 的 贡 献 是 m i n ( r − l + 1 , s i − s i − 1 ) 所以每个区间对答案的贡献是min(r-l+1,s_i-s_{i-1}) 所以每个区间对答案的贡献是min(r−l+1,si−si−1)
但 是 , 这 样 的 复 杂 度 还 不 够 优 秀 , 每 次 询 问 都 要 O ( n ) 的 时 间 来 求 \color{Red}但是,这样的复杂度还不够优秀,每次询问都要O(n)的时间来求 但是,这样的复杂度还不够优秀,每次询问都要O(n)的时间来求
所 以 我 们 把 所 有 的 s i − s i − 1 求 出 来 , 记 作 数 组 d [ i ] 所以我们把所有的s_i-s_{i-1}求出来,记作数组d[i] 所以我们把所有的si−si−1求出来,记作数组d[i]
那 么 显 然 , 如 果 d i > = r − l + 1 , 那 么 贡 献 r − l + 1 可 以 取 满 那么显然,如果d_i>=r-l+1,那么贡献r-l+1可以取满 那么显然,如果di>=r−l+1,那么贡献r−l+1可以取满
否 则 , 区 间 有 部 分 重 复 了 , 贡 献 为 d i 否则,区间有部分重复了,贡献为d_i 否则,区间有部分重复了,贡献为di
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1e5+10;
ll s[maxn],d[maxn],pre[maxn],n;
ll find(ll x)
{
ll l=1,r=n,mid;
while(r>l)
{
mid=l+r>>1;
if(d[mid]>=x) r=mid;
else l=mid+1;
}
return r;
}
int main()
{
cin >> n;
for(int i=1; i<=n ;i++) cin >> s[i];
sort(s+1,s+1+n);
for(int i=2;i<=n;i++) d[i-1]=s[i]-s[i-1];
sort(d+1,d+n);
cout<<endl;
for(int i=1;i<n;i++) pre[i]=pre[i-1]+d[i];
int q;cin>>q;
for(int i=1;i<=q;i++)
{
ll l,r;
cin>>l>>r;
ll len=r-l+1;
ll num=find(len);//num后的可以打满,之前的要减去d[i]
ll ans=len*(n-num+1)+pre[num-1];
cout<<ans<<" ";
}
}