思路:利用并查集将连在一起的乘法的结果存放在根节点,当成一个独立的区间,后面修改值的时候,先用总和sum减去这个值所在的区间s[i],之后用s[i]/a[i]*y就可以得到这个区间新的值,但是由于是边取模边计算的,所以s[i]/a[i]要转换为s[i]*a[i]^--1(用逆元来计算)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10,mod=1000000007;
int p[N],s[N],a[N];
char str[N];
int n,q;
int find(int x)
{
if(x!=p[x])
p[x]=find(p[x]);
return p[x];
}
int qmi(int a,int k,int p)
{
int res=1;
while(k)
{
if(k&1) res=(ll)res*a%p;
a=(ll)a*a%p;
k>>=1;
}
return res;
}
int main()
{
scanf("%d%d",&n,&q);
scanf("%s",str+1);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
s[i]=a[i];
p[i]=i;
}
for(int i=1;i<n;i++)
{
if(str[i]=='*')
{
int x=find(i),y=find(i+1);
p[x]=y;
s[y]=(ll)s[y]*s[x]%mod;
}
}
ll res=0;
for(int i=1;i<=n;i++)
if(i==find(i))
res=(res+s[i])%mod;
while(q--)
{
int x,y;
scanf("%d%d",&x,&y);
int t=find(x);
res=(res-(ll)s[t]+mod)%mod;
s[t]=(ll)s[t]*qmi(a[x],mod-2,mod)%mod*y%mod;//这里可以不用分出加法和乘法两种情况来写的,因为加法的话除以原来的那个数再乘y得到的就是y。
res=(res+s[t])%mod;
a[x]=y;
printf("%lld\n",res);
}
return 0;
}