大水題。
首先,若區間內只有一根弦,不會對答案有貢獻。
我們思考如何對答案產生貢獻。我們知道,對於每一個 \(s_i\),都會產生一段 \(s_i+r-l\) 的連續序列,在對 \(s\) 陣列排序後,若每個 \(s_i+r-l \ge s_{i+1}\) 則答案為 \(s_n+r-(s_1+l)+1\)。
若夠不到下一位呢?我們在 \(s_n+r-(s_1+l)+1\),上減去夠不到的位數即可。
過程的實現:我們先對 \(s\) 陣列排序,將 \(s_{i+1}-s_i \ge 2\) 的 \(s_{i+1}-s_i\) 壓入 \(c\) 陣列中,對 \(c\) 排序,並且求其字首和陣列 \(sum\)。設 \(c\) 陣列長度為 \(m\)。
對於詢問 \(l,r\),若 \(r-l\) 大於 \(c_m\),二分查詢 \(c\) 陣列中第一個大於 \(r-l\) 的數,\(c_x\)。夠不到的位數即為 sum[m]-sum[x-1]-ch*(m-x+1)
。用 \(s_n+r-(s_1+l)+1\) 減去即可。反之,輸出 \(s_n+r-(s_1+l)+1\) 即可。
程式碼(講的很詳細了不放註釋了):
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+7;
int a[N],sum[N],c[N];
int n,m;
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+1+n);
for(int i=2;i<=n;i++) {
if(a[i]-a[i-1]>1) c[++m]=a[i]-a[i-1]-1;
}
sort(c+1,c+1+m);
for(int i=1;i<=m;i++) sum[i]=sum[i-1]+c[i];
int qu;
cin>>qu;
while(qu--){
int l,r;
cin>>l>>r;
int ch=r-l,ans=a[n]+r-a[1]-l+1;
if(ch<c[m]) {
int w=upper_bound(c+1,c+1+m,ch)-c;
// cout<<w<<'\n';
int su=sum[m]-sum[w-1]-ch*(m-w+1);
ans-=su;
}
cout<<ans<<' ';
}
return 0;
}