题目描述
给定n个数a1,⋯ ,an。
对于一组配对(x,y),若对于所有的i=1,2,⋯ ,n,满足∣ax−ay∣≤∣ax−ai∣(i≠x),则称(x,y)为一组好的配对(|x|表示x的绝对值)。
给出若干询问,每次询问区间[l,r]中含有多少组好的配对。
即,取x,y(l≤x,y≤r),问有多少组(x,y)是好的配对。
输入格式
第一行两个正整数n,m。
第二行n个数a1,⋯ ,an。
接下来m行,每行给出两个数l,r。
输出格式
Ansi表示第i次询问的答案,输出 即可。
预处理配对
利用树状数组查找数量
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=3e5+10;
#define int long long
int n,m;
vector<int>p[N],p1[N],p2[N];
struct node{
int val,id;
}a[N];
inline bool cmp(node t1,node t2){
return t1.val<t2.val;
}
int c[N];
inline void add(int x,int y){
for(;x<=n;x+=x&(-x))c[x]+=y;
}
inline int sum(int x){
int res=0;
for(;x;x-=x&(-x))res+=c[x];
return res;
}
int ans[N];
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++)scanf("%lld",&a[i].val),a[i].id=i;
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++){
int Min=(1<<30);
if(i!=1)Min=min(Min,a[i].val-a[i-1].val);
if(i!=n)Min=min(Min,a[i+1].val-a[i].val);
if(i!=1&&a[i].val-a[i-1].val==Min)
p[min(a[i].id,a[i-1].id)].push_back(max(a[i].id,a[i-1].id));
if(i!=n&&a[i+1].val-a[i].val==Min)
p[min(a[i].id,a[i+1].id)].push_back(max(a[i].id,a[i+1].id));
}
for(int i=1,l,r;i<=m;i++){
scanf("%lld%lld",&l,&r);
p1[l].push_back(r);
p2[l].push_back(i);
}
for(int i=n;i>=1;i--){
for(int j=0;j<p[i].size();j++)add(p[i][j],1);
for(int j=0;j<p1[i].size();j++)ans[p2[i][j]]=sum(p1[i][j]);
}
int sum=0;
for(int i=1;i<=m;i++)sum+=ans[i]*i;
printf("%lld
",sum);
}