发现只用考虑每个值作为最大的时候即可
发现贡献可以看做平面上点和线段
扫描线即可
#include<bits/stdc++.h>
using namespace std;
#define re register
#define ll long long
#define pb push_back
#define cs const
#define bg begin
#define pii pair<int,int>
#define fi first
#define se second
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline char getc(){
char ch=gc();
while(!isalpha(ch))ch=gc();
return ch;
}
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=200005;
int n,m,p1,p2;
struct ask{
int l,r,coef,id;
ask(int _1=0,int _2=0,int _3=0,int _4=0):l(_1),r(_2),coef(_3),id(_4){}
};
vector<ask> q[N];
struct opt{
int l,r,val;
opt(int _1=0,int _2=0,int _3=0):l(_1),r(_2),val(_3){}
};
vector<opt> p[N];
namespace Seg{
int tag[N<<2];ll s[N<<2];
#define lc (u<<1)
#define rc ((u<<1)|1)
#define mid ((l+r)>>1)
inline void pushup(int u){
s[u]=s[lc]+s[rc];
}
inline void pushnow(int u,int l,int r,int k){
tag[u]+=k,s[u]+=1ll*(r-l+1)*k;
}
inline void pushdown(int u,int l,int r){
if(!tag[u])return ;
pushnow(lc,l,mid,tag[u]);
pushnow(rc,mid+1,r,tag[u]);
tag[u]=0;
}
void update(int u,int l,int r,int st,int des,int k){
if(st<=l&&r<=des)return pushnow(u,l,r,k);
pushdown(u,l,r);
if(st<=mid)update(lc,l,mid,st,des,k);
if(mid<des)update(rc,mid+1,r,st,des,k);
pushup(u);
}
ll query(int u,int l,int r,int st,int des){
if(st<=l&&r<=des)return s[u];
ll res=0;pushdown(u,l,r);
if(st<=mid)res+=query(lc,l,mid,st,des);
if(mid<des)res+=query(rc,mid+1,r,st,des);
pushup(u);return res;
}
}
int L[N],R[N],a[N];
int stk[N],top;
ll ans[N];
int main(){
#ifdef Stargazer
freopen("lx.cpp","r",stdin);
freopen("my.out","w",stdout);
#endif
n=read(),m=read(),p1=read(),p2=read();
for(int i=1;i<=n;i++)a[i]=read();a[n+1]=n+1;
for(int i=1;i<=n;i++){
while(top&&a[stk[top]]<a[i])top--;
L[i]=stk[top],stk[++top]=i;
}
stk[top=1]=n+1;
for(int i=n;i;i--){
while(top&&a[stk[top]]<a[i])top--;
R[i]=stk[top],stk[++top]=i;
}
for(int i=1;i<=n;i++){
int l=L[i],r=R[i];
if(l&&i+1<r)p[l].pb(opt(i+1,r-1,p2));
if(r<=n&&l+1<i)p[r].pb(opt(l+1,i-1,p2));
if(l)p[r].pb(opt(l,l,p1));
}
for(int i=1;i<=m;i++){
int l=read(),r=read();
q[l-1].pb(ask(l,r,-1,i));
q[r].pb(ask(l,r,1,i));
ans[i]=1ll*(r-l)*p1;
}
for(int i=1;i<=n;i++){
for(opt &x:p[i]){
Seg::update(1,1,n,x.l,x.r,x.val);
}
for(ask &x:q[i]){
ans[x.id]+=Seg::query(1,1,n,x.l,x.r)*x.coef;
}
}
for(int i=1;i<=m;i++)cout<<ans[i]<<'
';
}