题目大意
给出
1
到
定义第一类点对
(i,j)
满足
i<j
,且
max{ks|i<s<j}<min(ki,kj)
;
定义第二类点对
(i,j)
满足
i<j
,且
min(ki,kj)<max{ks|i<s<j}<max(ki,kj)
.
之后给出
m
个询问,每次询问一个区间
数据范围
1≤n,m≤200000,1≤p1,p2≤1000 .
解题报告
定义第三类点对 (i,j) 满足 i<j ,且 max{ks|i<s<j}<max(ki,kj) ,记第三类点对的数量为 s3 ,则有 s2=s3−s1 .
考虑
s1
的计算方法:
如果
ki<kj
,那么
j
只能是
记
previ
为
i
左边第一个比
考虑
s3
的计算方法:
如果
ki<kj
,则区间
[i,j]
在
j
处取得最大值;如果
则如果固定
有了前面的结论之后,我们可以使用一种离线算法从左到右、从右到左分别计算 ki<kj 和 kj<ki 的情况。
对于
ki<kj
的情况,将询问
[a,b]
拆为
Q(b,a,b)−Q(a−1,a,b)
,
Q(i,l,r)
表示右端点小于等于
i
,左端点属于
不断移动右端点,当右端点移动到
i
时,用单调栈求出
对于 kj<ki 的情况,与 ki<kj 类似,不再赘述。
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int gint(){
char c; int f=1;
while(c=getchar(),c<48||c>57)
if(c=='-')f=-1;
int x=0;
for(;c>47&&c<58;c=getchar()){
x=x*10+c-48;
}
return x*f;
}
#define max_N 200005
typedef long long ll;
int n,m,p1,p2,l[max_N],r[max_N],k[max_N];
ll cnt1[max_N],cnt2[max_N];
struct QY{
int l,r,id,f,next;
QY(int l=0,int r=0,int id=0,int f=0,int n=0):
l(l),r(r),id(id),f(f),next(n){}
}Q[max_N<<1];
int head[max_N],tot;
inline void add_QY(int x,int l,int r,int id,int f){
if(x&&x<=n)Q[++tot]=QY(l,r,id,f,head[x]),head[x]=tot;
}
int st[max_N],top;
int bit1[max_N],bit2[max_N];
ll bit3[max_N];
inline int sum(int x){
int res=0;
for(;x;x-=x&-x)res+=bit1[x];
return res;
}
inline void add(int x,int y){
if(x>1){
for(int i=1;i<=n;i+=i&-i)bit2[i]+=y;
for(int i=x;i<=n;i+=i&-i)bit2[i]-=y;
}
for(int i=x;i&&i<=n;i+=i&-i)bit3[i]+=x*y;
}
inline void modify(int l,int r){
if(l>r)return;
add(l-1,-1),add(r,1);
}
inline ll query(int x){
ll res=0;
for(int i=x;i;i-=i&-i){
res+=1ll*x*bit2[i]+bit3[i];
}
return res;
}
inline ll query(int l,int r){
return query(r)-query(l-1);
}
int main(){
n=gint(),m=gint(),p1=gint(),p2=gint();
for(int i=1;i<=n;++i)k[i]=gint();
for(int i=1;i<=m;++i){
l[i]=gint(),r[i]=gint();
add_QY(l[i]-1,l[i],r[i],i,-1),add_QY(r[i],l[i],r[i],i,1);
}
st[top=0]=0;
for(int x=1;x<=n;++x){
while(top&&k[st[top]]<k[x])--top;
for(int i=st[top];i&&i<=n;i+=i&-i)++bit1[i];
modify(st[top]+1,x-1);
for(int i=head[x];i;i=Q[i].next){
cnt1[Q[i].id]+=(sum(Q[i].r)-sum(Q[i].l-1))*Q[i].f;
cnt2[Q[i].id]+=query(Q[i].l,Q[i].r)*Q[i].f;
}
st[++top]=x;
}
tot=0;
for(int i=1;i<=n;++i)head[i]=bit1[i]=bit2[i]=bit3[i]=0;
for(int i=1;i<=m;++i){
add_QY(l[i],l[i],r[i],i,1),add_QY(r[i]+1,l[i],r[i],i,-1);
}
st[top=0]=n+1;
for(int x=n;x;--x){
while(top&&k[st[top]]<k[x])--top;
for(int i=st[top];i&&i<=n;i+=i&-i)++bit1[i];
modify(x+1,st[top]-1);
for(int i=head[x];i;i=Q[i].next){
cnt1[Q[i].id]+=(sum(Q[i].r)-sum(Q[i].l-1))*Q[i].f;
cnt2[Q[i].id]+=query(Q[i].l,Q[i].r)*Q[i].f;
}
st[++top]=x;
}
for(int i=1;i<=m;++i){
printf("%lld\n",cnt1[i]*p1+(cnt2[i]-cnt1[i])*p2);
}
return 0;
}