#1116 : 计算

描述

现在有一个有n个元素的数组a1, a2, ..., an。

记f(i, j) = ai * ai+1 * ... * aj。

初始时,a1 = a2 = ... = an = 0,每次我会修改一个ai的值,你需要实时反馈给我 ∑1 <= i <= j <= n f(i, j)的值 mod 10007。

输入

第一行包含两个数n(1<=n<=100000)和q(1<=q<=500000)。

接下来q行,每行包含两个数i, x,代表我把ai的值改为了x。

输出

分别输出对应的答案,一个答案占一行。

样例输入

5 5
1 1
2 1
3 1
4 1
5 1

样例输出

1
3
6
10
15

考虑用线段树解决。设sumv[o]表示区间[l,r]的答案,那么首先sumv[o]=sumv[lc]+sumv[rc],加上跨越中线的答案即可。
用ls[o]表示后缀的乘积之和,rs[o]表示前缀的乘积之和,维护一下即可。
#include<cstdio>
#include<cctype>
#include<queue>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
typedef long long ll;
const int maxn=100010;
const int mod=10007;
ll sumv[maxn*3],ls[maxn*3],rs[maxn*3],xp[maxn*3];
void update(int o,int l,int r,int x,ll v) {
    if(l==r) ls[o]=rs[o]=sumv[o]=xp[o]=v;
    else {
        int mid=l+r>>1,lc=o<<1,rc=lc|1;
        if(x<=mid) update(lc,l,mid,x,v);
        else update(rc,mid+1,r,x,v);
        xp[o]=(xp[lc]*xp[rc])%mod;
        sumv[o]=(sumv[lc]+sumv[rc]+ls[rc]*rs[lc])%mod;
        ls[o]=(ls[lc]+ls[rc]*xp[lc])%mod;
        rs[o]=(rs[rc]+rs[lc]*xp[rc])%mod;
    }
}
int main() {
    int n=read(),m=read();
    while(m--) {
        int x=read(),v=read();
        update(1,1,n,x,v);
        printf("%lld
",sumv[1]);
    }
    return 0;
}
View Code
 
原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4812973.html