首先 具体有哪些点对我们是很好找到的
问题转化为 多次询问区间 有多少点对
对于多次区间离线询问 考虑定一边R 从左到右依次选择
对询问的R从小到大排序
这题树状数组还是很好想的 考虑一个点对【l,r】 一个询问【L,R】
如果r>R 那么这个区间一定不会考虑这个点对 所以有点对r<=R时才加入树状数组
对于每个点对【l,r】l加入树状数组 每次询问 只询问l>=L的点就好
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
const int maxn=3e5+5;
int n,m,cnt;
int c[maxn];
void upd(int x){
while(x<maxn)c[x]++,x+=lowbit(x);
}
int query(int x){
int res=0;
while(x)res+=c[x],x-=lowbit(x);
return res;
}
struct node{
int val,id;
}a[maxn];
struct ee{
int L,R,ii;
}p[maxn],ask[maxn];
bool cmp(node aa,node bb){
return aa.val<bb.val;
}
bool cmp1(ee aa,ee bb){
return aa.R<bb.R;
}
void add(int k1,int k2){
p[++cnt].L=min(k1,k2);
p[cnt].R=max(k1,k2);
}
int main(){
cin>>n>>m;
if(n==1){
cout<<"0"<<endl;
return 0;
}
for(int i=1;i<=n;i++)scanf("%d",&a[i].val),a[i].id=i;
sort(a+1,a+1+n,cmp);
add(a[1].id,a[2].id);
add(a[n-1].id,a[n].id);
for(int i=2;i<=n-1;i++){
int c1=a[i].val-a[i-1].val;
int c2=a[i+1].val-a[i].val;
if(c1>c2)add(a[i+1].id,a[i].id);
else if(c1<c2)add(a[i-1].id,a[i].id);
else add(a[i+1].id,a[i].id),add(a[i].id,a[i-1].id);
}
for(int i=1;i<=m;i++)
scanf("%d%d",&ask[i].L,&ask[i].R),ask[i].ii=i;
sort(ask+1,ask+1+m,cmp1);
sort(p+1,p+1+cnt,cmp1);
ll j=1,res=0;
for(int i=1;i<=m;i++){
while(j<=cnt&&p[j].R<=ask[i].R){
upd(p[j].L);
j++;
}
res+=1ll*ask[i].ii*(j-1-query(ask[i].L-1));
}
cout<<res<<endl;
return 0;
}