1. 程式人生 > >[HNOI2017] bzoj 4826 影魔

[HNOI2017] bzoj 4826 影魔

題目大意:給一個排列p,多次詢問一個區間[l,r]的中有多少子區間[i,j]滿足: mx(i+1,j1)min(p[i],p[j])mx(i+1,j-1)\le min(p[i],p[j])(記做cnt1),或者min(p[i],p[j])<mx(i+1,j1)<max(p[i],p[j])min(p[i],p[j])<mx(i+1,j-1)<max(p[i],p[j])(記做cnt2),並輸出c

nt1q1+cnt2q2cnt1*q1+cnt2*q2。其中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; }