Loading

BZOJ 4826 影魔

本题可以采用主席树的在线做法,只不过常数会 \(super\) 大。

和其他题解差不多,我们先要求出第 \(i\) 个数的 \(l_i\)\(r_i\) ,其中 \(l_i\) 表示左边第一个比它大的点(若没有则为 \(0\) ), \(r_i\) 表示右边比它大的第一个点,若没有则为 \(n+1\)

那么对于 \(i\)

  1. 点对 \((l_i,r_i)\) 可以有 \(p_1\) 的贡献

  2. 点对 \(([l_i+1,i-1],r_i),(l_i,[i+1,r_i-1])\) 可以有 \(p_2\) 的贡献 \((l_i+1<i-1),(i+1<r_i-1)\)

  3. \((i,i+1)\) 也可以有 \(p_1\) 的贡献

有了这么几点,我们就可以拿主席树来维护,对于每个点对,我们以 \(x\) 更新,若 \(x\) 为区间,则以 \(y\) 更新。

用一个单调栈预处理,链表(或 \(vector\) 存储更新信息)。

\(AC \kern 0.4emCODE\):

#include<bits/stdc++.h>
#define ri register int
#define p(i) ++i
#define LL long long
using namespace std;
const int N=2e5+7;
inline int read() {
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
struct node{
	int l,r,w;
	node(){}
	node(int l,int r,int w):l(l),r(r),w(w){}
};
struct E{
	int first[N],t;
	void init() {t=1;}
	struct edge{
		int nxt;
		node v;
	}e[N<<2];
	inline void add(int u,node v) {
		e[t].v=v;
		e[t].nxt=first[u];
		first[u]=t++;
	} 
}E;
struct Seg{
	int root[N],tot;
	struct Segmenttree{
		int l,r;
		LL sum,tag;
	}T[N*32];
	inline void update(int &x,int l,int r,int lt,int rt,int w) {
		if (!x) x=p(tot);
		T[x].sum+=1ll*(min(r,rt)-max(l,lt)+1)*w;
		if (l<=lt&&rt<=r) {T[x].tag+=1ll*w;return;}
		int mid=(lt+rt)>>1;
		if (l<=mid) update(T[x].l,l,r,lt,mid,w);
		if (r>mid) update(T[x].r,l,r,mid+1,rt,w);
	}
	inline int merge(int x,int y) {
		if (!x||!y) return x+y;
		T[x].sum+=T[y].sum;T[x].tag+=T[y].tag;
		T[x].l=merge(T[x].l,T[y].l);
		T[x].r=merge(T[x].r,T[y].r);
		return x;
	}
	inline LL query(int x,int l,int r,int lt,int rt) {
		if (!x) return 0;
		if (l<=lt&&rt<=r) return T[x].sum;
		int mid=(lt+rt)>>1;LL res=0;
		if (l<=mid) res+=query(T[x].l,l,r,lt,mid);
		if (r>mid) res+=query(T[x].r,l,r,mid+1,rt);
		return res+1ll*(min(r,rt)-max(l,lt)+1)*T[x].tag;
	}
}T;
int n,st[N],p,pp,at[N],ll[N],rr[N],m;
int main() {
	n=read(),m=read(),p=read(),pp=read();
	const int p1=p,p2=pp;
	int tp=0;
	for (ri i(1);i<=n;p(i)) {
		at[i]=read();
		while(tp&&at[st[tp]]<at[i]) rr[st[tp--]]=i;
		ll[i]=st[tp];
		st[p(tp)]=i;
	}
	while(tp) rr[st[tp--]]=n+1;
	E.init();
	for (ri i(1);i<=n;p(i)) {
		if (i!=n) E.add(i,node(i+1,i+1,p1));
		if (ll[i]&&rr[i]<=n) E.add(ll[i],node(rr[i],rr[i],p1));
		if (ll[i]&&i+1<=rr[i]-1) E.add(ll[i],node(i+1,rr[i]-1,p2));
		if (rr[i]<=n&&ll[i]+1<=i-1) E.add(rr[i],node(ll[i]+1,i-1,p2));
	}
	for (ri i(1);i<=n;p(i)) {
		for (ri j(E.first[i]);j;j=E.e[j].nxt) {
			node v=E.e[j].v;
			int l=v.l,r=v.r,w=v.w;
			T.update(T.root[i],l,r,1,n,w);
		}
		T.root[i]=T.merge(T.root[i],T.root[i-1]);
	}
	for (ri i(1);i<=m;p(i)) {
		int l=read(),r=read();
		printf("%lld\n",T.query(T.root[r],l,r,1,n)-T.query(T.root[l-1],l,r,1,n));
	}
	return 0;
}
posted @ 2021-04-09 15:58  ナンカエデ  阅读(139)  评论(1编辑  收藏  举报