bzoj4597: [Shoi2016]随机序列

Posted f321dd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4597: [Shoi2016]随机序列相关的知识,希望对你有一定的参考价值。

容易推出答案为$\sum_{i=1}^{n-1}2*3^{n-i-1}\prod_{j=1}^{i}a_{j}+\prod_{j=1}^{n}a_{j}$。然后随便怎么维护都行,我没多想直接用的区间乘区间和来搞,其实可以直接维护乘积和答案。

#include<cstdio>
#define Z int l=1,int r=n,int k=1
#define N 100005
#define M (l+r>>1)
#define P (k<<1)
#define S (k<<1|1)
#define L l,M,P
#define R M+1,r,S
int n,m,s,t;
typedef long long ll;
const ll p=1e9+7;
ll f[N],e[N],a[N];
ll u[N*4],v[N*4];
void apply(ll a,int k){
	u[k]=u[k]*a%p;
	v[k]=v[k]*a%p;
}
void devolve(int k){
	if(v[k]!=1){
		apply(v[k],P);
		apply(v[k],S);
		v[k]=1;
	}
}
void update(int k){
	u[k]=(u[P]+u[S])%p;
}
void build(Z){
	if(l==r)
		u[k]=a[l];
	else{
		build(L);
		build(R);
		update(k);
	}
	v[k]=1;
}
void amend(ll a,int s,
int t,Z){
	if(s<=l&&r<=t)
		apply(a,k);
	else{
		devolve(k);
		if(s<=M)
			amend(a,s,t,L);
		if(t>M)
			amend(a,s,t,R);
		update(k);
	}
}
ll pow(ll u,ll k){
	ll a=1;
	for(;k;k>>=1){
		if(k%2)a=a*u%p;
		if(k/2)u=u*u%p;
	}
	return a;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
		scanf("%lld",e+i);
	f[f[0]=a[0]=1]=2;
	for(int i=2;i<n;++i)
		f[i]=f[i-1]*3%p;
	for(int i=1;i<=n;++i)
		a[i]=a[i-1]*e[i]%p;
	for(int i=1;i<=n;++i)
		a[i]=a[i]*f[n-i]%p;
	build();
	while(m--){
		scanf("%d%d",&s,&t);
		t=t*pow(e[s],p-2)%p;
		amend(t,s,n);
		e[s]=e[s]*t%p;
		printf("%lld\n",u[1]);
	}
}

  

以上是关于bzoj4597: [Shoi2016]随机序列的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 4597 随机序列

BZOJ 4597 随机序列

SHOI2016 随机序列

P4340 [SHOI2016]随机序列(线段树)

BZOJ2830 & 洛谷3830:[SHOI2012]随机树——题解

bzoj3304[Shoi2005]带限制的最长公共子序列 DP