rt,本来写了个莫队,结果T了一个点。于是加了个奇偶优化,虽然没TLE了,但居然WA了...本来AC的几个点也WA掉了。
求助各位。代码:
#include <bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c&15);c=getchar();}
return x*f;
}
const int MAXN=3e5+7;
int n,m;
long long ANS;
struct ARR{
int pos;
long long sum;
bool operator < (const ARR &a) const{return sum<a.sum;}
}arr[MAXN];
int len,num,L[MAXN],R[MAXN],block[MAXN];
void build(){
len=sqrt(n);
num=ceil(n*1.0/len);
for(int i=1;i<=num;i++){
L[i]=R[i-1]+1;
R[i]=i*len;
}
R[num]=n;
for(int i=1;i<=num;i++)
for(int j=L[i];j<=R[i];j++)
block[j]=i;
}
struct QUE{
int l,r,id;
long long ans;
bool operator < (const QUE &x) const{return block[l]^block[x.l]?block[l]<block[x.l]:r<x.r;}
}que[MAXN];
bool _cmp(ARR a,ARR b){
return a.pos<b.pos;
}
bool cmp(QUE a,QUE b){
return a.id<b.id;
}
int g[MAXN][2];
long long cnt[MAXN];
long long ans;
int l=1,r=0;
void add(int x){
for(int i=0;i<=1;i++) if(~g[x][i]) if(l<=g[x][i]&&r>=g[x][i]) ans++;//计算x本身对答案的贡献
for(int i=0;i<=1;i++) if(~g[x][i]) cnt[g[x][i]]++;//先算上位置x对cnt的影响
ans+=cnt[x];//再加上算了x的所有贡献
}
void del(int x){
ans-=cnt[x];//先把所有配对数字位于x上的贡献减掉,要先写这个,把x也算上
for(int i=0;i<=1;i++) if(~g[x][i]) cnt[g[x][i]]--;//再把位置x弄走
for(int i=0;i<=1;i++) if(~g[x][i]) if(l<=g[x][i]&&r>=g[x][i]) ans--;//计算x本身对答案的贡献
}
void calc(){//把一个数字产生的贡献放到其配对数字上,区间的改变的同时维护这个贡献的正确性,方便统计。
//也就是说,一个加贡献,另一个数字统计贡献,就能保证当且仅当两个数字都在区间内时会算上。
for(int i=1;i<=m;i++){
while(r<que[i].r) add(++r);
while(r>que[i].r) del(r--);
while(l>que[i].l) add(--l);
while(l<que[i].l) del(l++);
que[i].ans=ans;
}
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++) arr[i].pos=i,arr[i].sum=read();
sort(arr+1,arr+n+1);
arr[0].sum=-999999999999999999;
arr[n+1].sum=999999999999999999;//处理越界问题
memset(g,-1,sizeof(g));
for(int i=1;i<=n;i++)
if((arr[i].sum-arr[i-1].sum)^(arr[i+1].sum-arr[i].sum))
g[arr[i].pos][0]=arr[i].sum-arr[i-1].sum<arr[i+1].sum-arr[i].sum?arr[i-1].pos:arr[i+1].pos;
else g[arr[i].pos][0]=arr[i-1].pos,g[arr[i].pos][1]=arr[i+1].pos;
sort(arr+1,arr+n+1,_cmp);
for(int i=1;i<=m;i++) que[i].l=read(),que[i].r=read(),que[i].id=i;
// for(int i=1;i<=n;i++) for(int j=0;j<g[i].size();j++) printf("%d\n",g[i][j]);
build();
sort(que+1,que+m+1);
calc();
sort(que+1,que+m+1,cmp);
for(int i=1;i<=m;i++) ANS+=i*que[i].ans;//printf("%lld\n",que[i].ans);
printf("%lld\n",ANS);
return 0;
}