发现对于除了全是乘法之外的任意一个序列,有一个与之一一对应的序列,两个序列相加后除了第一项全部抵消,所以只有前缀积被记入答案,第n个元素的前缀积被计算了一次,对于1<=i<n,到第i个元素的前缀积被计算了2*3^(n-i-1)次,答案即为sigma 第i个前缀积被计算的次数*第i个前缀积
更改一个数相当于对他和他后面的所有前缀积乘上这个数的逆元再乘上新数
线段树维护即可
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define MAXN 100010
#define MAXM 1010
#define ll long long
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
int n,m;
ll a[MAXN];
ll s[MAXN];
ll v[MAXN*4],ch[MAXN*4];
ll tim[MAXN];
ll mi(ll x,ll y){
ll re=1;
while(y){
if(y&1){
re=re*x%MOD;
}
x=x*x%MOD;
y>>=1;
}
return re;
}
ll ni(ll x){
return mi(x,MOD-2);
}
inline void toch(int x,ll y){
v[x]=v[x]*y%MOD;
ch[x]=ch[x]*y%MOD;
}
inline void ud(int x){
v[x]=(v[x<<1]+v[x<<1|1])%MOD;
}
inline void pd(int x){
if(ch[x]!=1){
toch(x<<1,ch[x]);
toch(x<<1|1,ch[x]);
ch[x]=1;
}
}
void build(int x,int y,int z){
ch[x]=1;
if(y==z){
v[x]=s[y]*tim[y]%MOD;
return ;
}
int mid=y+z>>1;
build(x<<1,y,mid);
build(x<<1|1,mid+1,z);
ud(x);
}
void change(int x,int y,int z,int l,int r,ll cv){
if(y==l&&z==r){
toch(x,cv);
return ;
}
pd(x);
int mid=y+z>>1;
if(r<=mid){
change(x<<1,y,mid,l,r,cv);
}else if(l>mid){
change(x<<1|1,mid+1,z,l,r,cv);
}else{
change(x<<1,y,mid,l,mid,cv);
change(x<<1|1,mid+1,z,mid+1,r,cv);
}
ud(x);
}
int main(){
int i,x,y;
scanf("%d%d",&n,&m);
s[0]=1;
ll t=0;
for(i=1;i<n;i++){
tim[i]=2*mi(3,n-i-1);
}
tim[n]=1;
for(i=1;i<=n;i++){
scanf("%lld",&a[i]);
s[i]=s[i-1]*a[i]%MOD;
(t+=s[i])%=MOD;
}
build(1,1,n);
for(i=1;i<=m;i++){
scanf("%d%d",&x,&y);
change(1,1,n,x,n,ni(a[x])*(a[x]=y)%MOD);
printf("%lld\n",v[1]);
}
return 0;
}
/*
5 5
9384 887 2778 6916 7794
2 8336
5 493
3 1422
1 28
4 60
*/