【LOJ#2019】【AHOI / HNOI2017】—影魔(线段树+扫描线)

传送门

发现只用考虑每个值作为最大的时候即可
发现贡献可以看做平面上点和线段
扫描线即可

#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]<<'\n';
}
posted @ 2019-10-29 18:59  Stargazer_cykoi  阅读(133)  评论(0编辑  收藏  举报