LGP4340题解

看到加减想抵消

我们来思考一件很许可的事情:对于一个表达式,其值一定是类似 \(\sum_{i=1}^{m}c_i\times prod_i\) 类似的办法算出来的。就是一堆区间的乘积再加上符号。

可以发现,除了第一个 \(prod_i\),后面的 \(prod\) 都会被抵消掉。

所以我们只需要枚举第一个 \(prod\) 的长度就完事了。

推一下柿子:

\[\sum_{i=1}^{n}\prod_{k=1}^{i}a_k\times 2\times 3^{n-i-1}+\frac{\prod_{i=1}^{n}a_i}{3} \]

\[2\times 3^{n-1}\times\sum_{i=1}^{n}\prod_{k=1}^{i}\frac{a_k}{3}+\frac{\prod_{i=1}^{n}a_i}{3} \]

问题变为单点修改,求 \(\sum_{i=1}^{n}\prod_{k=1}^{i}a_k+\frac{\prod_{i=1}^{n}a_i}{3}\)

线段树,维护每个区间所有前缀的积之和与整个区间的积就完了。

#include<cstdio>
typedef unsigned ui;
const ui M=1e5+5,inv3=333333336,mod=1e9+7;
ui n,m,ans[M<<2],prod[M<<2];
inline void Build(const ui&u,const ui&L=1,const ui&R=n){
	if(L==R){
		ui V;scanf("%u",&V);ans[u]=prod[u]=1ull*V*inv3%mod;return;
	}
	const ui&mid=L+R>>1;Build(u<<1,L,mid);Build(u<<1|1,mid+1,R);
	ans[u]=(ans[u<<1]+1ull*prod[u<<1]*ans[u<<1|1])%mod;prod[u]=1ull*prod[u<<1]*prod[u<<1|1]%mod;
}
inline void Modify(const ui&u,const ui&x,const ui&V,const ui&L=1,const ui&R=n){
	if(L==R)return ans[u]=prod[u]=V,void();
	const ui&mid=L+R>>1;x<=mid?Modify(u<<1,x,V,L,mid):Modify(u<<1|1,x,V,mid+1,R);
	ans[u]=(ans[u<<1]+1ull*prod[u<<1]*ans[u<<1|1])%mod;prod[u]=1ull*prod[u<<1]*prod[u<<1|1]%mod;
}
signed main(){
	ui x,y,c1(2),c2(1);scanf("%u%u",&n,&m);Build(1,1,n);for(ui i=1;i<n;++i)c1=3ull*c1%mod,c2=3ull*c2%mod;
	while(m--)scanf("%u%u",&x,&y),Modify(1,x,1ull*inv3*y%mod),printf("%u\n",(1ull*c1*ans[1]+1ull*c2*prod[1])%mod);
}
posted @ 2022-03-31 15:52  Prean  阅读(15)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};