题解 | 小沙的算数
小沙的算数
https://ac.nowcoder.com/acm/contest/23477/F
-
写一个极简版的,思路:保存每一个有效数区间 例如 2+432+53+2 那就有4个区间要保存,分别为2,432,53,2用一个数组保存他们对应的值,考虑到一个区间中所有元素都要能查询到这个值,可以用两种方法
-
- 运用并查集,将乘法块中的每个数都指向其第一个元素
-
- 运用一个指针数组,pos[i]=cnt,来指向;
这里我们选用方法2 ,对于最开始有效块的处理是需要注意的,想了挺久如何简化这个代码
for(int i=2;i<=n;i++){
if(s[i-1]=='*'){
pos[i]=cnt;
num[cnt]=num[cnt]*a[i]%mod;
}
else{
num[++cnt]=a[i];
pos[i]=cnt;
}
}
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int N = 1e6+8;
char s[N];
ll num[N],pos[N],n,q,a[N];
ll ksm(ll a, ll b) {
ll ans = 1;
for (; b; b >>= 1, (a *= a) %= mod)
if (b & 1)(ans *= a) %= mod;
return ans;
}
int main()
{
cin>>n>>q;
scanf("%s",s+1);
for(int i=1;i<=n;i++)cin>>a[i];
int cnt=1;
num[1]=a[1];
pos[1]=1;
for(int i=2;i<=n;i++){
if(s[i-1]=='*'){
pos[i]=cnt;
num[cnt]=num[cnt]*a[i]%mod;
}
else{
num[++cnt]=a[i];
pos[i]=cnt;
}
}
ll ans = 0,x=0,y=0;
for(int i=1;i<=cnt;i++)ans=(ans+num[i])%mod;
while(q--){
cin>>x>>y;
ans=(ans-num[pos[x]]+mod)%mod;
num[pos[x]]=num[pos[x]]*ksm(a[x],mod-2)%mod*y%mod;
ans=(ans+num[pos[x]])%mod;
a[x]=y;
cout<<ans<<endl;
}
}