[HNOI2017] bzoj 4826 影魔
阿新 • • 發佈:2018-12-17
題目大意:給一個排列p,多次詢問一個區間[l,r]的中有多少子區間[i,j]滿足: (記做cnt1),或者(記做cnt2),並輸出。其中mx為區間p的最大值。 題解: 考慮對mx統計。設a[c]=mx(i+1,j-1)。記L[c]為c左第一個比c大的數字的位置。 若a[c]對cnt1有貢獻,則i=L[c],j=R[c],此時若詢問l,r包含i,j,則對cnt1有1的貢獻。同裡,當選i=L[c],c+1<=j<=R[c]的時候或者同理,會對答案有cnt2的貢獻。 然後做掃描線即可,正反做兩邊線段樹維護一下。
#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define N 200010
#define db double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
struct segment{
int l,r;lint s,pt;
segment *ch[2];
}*rt;int a[N],L[N],R[N],s[N],ql[N],qr[N];
int build(segment* &rt,int l,int r)
{
rt=new segment,rt->l=l,rt->r=r,rt->s=rt->pt=0;
int mid=(l+r)>>1;if(l==r) return 0;
return build(rt->ch[0],l,mid),build(rt->ch[1],mid+1,r);
}
inline int update_tags(segment* &rt,lint v) { return rt->s+=(rt->r-rt->l+1)*v,rt->pt+=v,0; }
inline int push_up(segment* &rt) { return rt->s=rt->ch[0]->s+rt->ch[1]->s,0; }
inline int push_down(segment* &rt) { return update_tags(rt->ch[0],rt->pt),update_tags(rt->ch[1],rt->pt),rt->pt=0,0; }
int update(segment* &rt,int s,int t,int v)
{
int l=rt->l,r=rt->r,mid=(l+r)>>1;
if(s<=l&&r<=t) return update_tags(rt,v);
if(rt->pt) push_down(rt);
if(s<=mid) update(rt->ch[0],s,t,v);
if(mid<t) update(rt->ch[1],s,t,v);
return push_up(rt),0;
}
lint query(segment* &rt,int s,int t)
{
int l=rt->l,r=rt->r,mid=(l+r)>>1;
if(s<=l&&r<=t) return rt->s;
if(rt->pt) push_down(rt);lint ans=0;
if(s<=mid) ans+=query(rt->ch[0],s,t);
if(mid<t) ans+=query(rt->ch[1],s,t);
return ans;
}
vector<pii> q1[N],q2[N];lint ans[N];
vector< pair<pii,int> > v1[N],v2[N];
char ss[N*22],tt[25];int ssl,ttl;
inline int show(lint x)
{
if(!x) ss[++ssl]='0';
for(ttl=0;x;x/=10) tt[++ttl]=char(x%10+'0');
for(;ttl;ttl--) ss[++ssl]=tt[ttl];
return ss[++ssl]='\n';
}
int main()
{
int n=inn(),q=inn(),p1=inn(),p2=inn();
rep(i,1,n) a[i]=inn();int t=0,x,y;
rep(i,1,q) x=ql[i]=inn(),y=qr[i]=inn(),q1[y].pb(mp(x,i)),q2[x].pb(mp(y,i));
for(int i=1;i<=n;s[++t]=i++) while(t&&a[s[t]]<a[i]) R[s[t--]]=i;
while(t) R[s[t--]]=n+1;
for(int i=n;i>=1;s[++t]=i--) while(t&&a[s[t]]<a[i]) L[s[t--]]=i;
while(t) L[s[t--]]=0;
rep(c,1,n)
{
if(L[c]>=1&&R[c]<=n) v1[R[c]].pb(mp(mp(L[c],L[c]),p1));
if(R[c]<=n&&c-1>=L[c]+1) v1[R[c]].pb(mp(mp(L[c]+1,c-1),p2));
if(L[c]>=1&&c+1<=R[c]-1) v2[L[c]].pb(mp(mp(c+1,R[c]-1),p2));
}
build(rt,1,n);
rep(i,1,n)
{
Rep(j,v1[i]) update(rt,v1[i][j].fir.fir,v1[i][j].fir.sec,v1[i][j].sec);
Rep(j,q1[i]) ans[q1[i][j].sec]+=query(rt,q1[i][j].fir,i);
}
build(rt,1,n);
for(int i=n;i;i--)
{
Rep(j,v2[i]) update(rt,v2[i][j].fir.fir,v2[i][j].fir.sec,v2[i][j].sec);
Rep(j,q2[i]) ans[q2[i][j].sec]+=query(rt,i,q2[i][j].fir);
}
rep(i,1,q) show(ans[i]+(qr[i]-ql[i])*p1);
return fwrite(ss+1,sizeof(char),ssl,stdout),0;
}