hiho1116 - 数据结构 线段树(区间合并)
现在有一个有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。
/*******************************************************/
记两个数的区间【a,b】
[a,b].sum = a+b+a*b;
[a,b].prefix = a+a*b;
[a,b].suffix = b+a*b;
[a,b].product = a*b;
当合并区间【a,b】和【c,d】时
有[a,b,c,d].sum = [a,b].sum+[c,d].sum+[a,b].suffix*[c,d].prefix;
[a,b,c,d].product = a*b*c*d = [a,b].product*[c,d].product;
.product的存在是为了维护prefix和suffix,因为:
[a,b,c,d].prefix = [a,b].prefix + [a,b].product*[c,d].prefix;
[a,b,c,d].suffix = [c,d].suffix + [c,d].product*[a,b].suffix;
#include <cstdio> #include <cstring> const int N = 100100; const int MOD = 10007; struct NODE{ int l,r; int sum; int prefix,suffix,product; NODE(){ sum = prefix = suffix = product = 0; } int MID(){ return (l+r)>>1; } }; NODE segtree[N*3]; void build(int id,int l,int r){ segtree[id].l = l; segtree[id].r = r; if(l==r) return ; int mid = (l+r)>>1; build(id*2,l,mid); build(id*2+1,mid+1,r); } void modify(int id,int pos,int value){ if((segtree[id].l==segtree[id].r)&&(segtree[id].l==pos)){ segtree[id].sum = segtree[id].prefix = segtree[id].suffix = segtree[id].product = (value)%MOD; return ; } int mid = segtree[id].MID(); if(pos<=mid) modify(id*2,pos,value); else modify(id*2+1,pos,value); segtree[id].sum = ((segtree[id*2].sum+segtree[id*2+1].sum)+(segtree[id*2].suffix*segtree[id*2+1].prefix)%MOD)%MOD; segtree[id].prefix = (segtree[id*2].prefix+(segtree[id*2].product*segtree[id*2+1].prefix)%MOD)%MOD; segtree[id].suffix = (segtree[id*2+1].suffix+(segtree[id*2+1].product*segtree[id*2].suffix)%MOD)%MOD; segtree[id].product = (segtree[id*2].product*segtree[id*2+1].product)%MOD; } int main(){ int n,q,a,b; scanf("%d%d",&n,&q); build(1,1,n); while(q--){ scanf("%d%d",&a,&b); modify(1,a,b); printf("%d\n",segtree[1].sum); } return 0; }