时间限制:
4000ms
单点时限:
1000ms
内存限制:
256MB
-
5 5 1 1 2 1 3 1 4 1 5 1
样例输出
-
1 3 6 10 15
描述
现在有一个有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。
输出
分别输出对应的答案,一个答案占一行。
题意:求所有子区间乘积之和。
思路:线段树可在logn时间复杂度内完成对区间的修改与查询。不过,这道题要定义一个数据结构
struct Node {
int l, r;
_long all, lseg, rseg, mul;
}
all:题目答案,lseg:区间所有前缀乘积之和,rseg:区间所有后缀乘积之和,mul:区间所有元素乘积。下面请看一组例子加深对本数据结构的理解。
例:
[3 4 2 5]
all:3 + 3*4 + 4*2 + 2*5 + 3*4*2 + 4*2*5 + 3*4*2*5
lseg:3 + 3*4 + 3*4*2 + 3*4*2*5
rseg:3*4*2*5 + 4*2*5 + 2*5 + 5
mul:3*4*2*5
那么,区间是这样合并的:
a[rt].all = (a[rt << 1].all + a[(rt << 1) | 1].all + a[rt << 1].rseg * a[(rt << 1) | 1].lseg) % MOD;
a[rt].lseg = (a[rt << 1].lseg + a[rt << 1].mul * a[(rt << 1) | 1].lseg) % MOD;
a[rt].rseg = (a[(rt << 1) | 1].rseg + a[(rt << 1) | 1].mul * a[rt << 1].rseg) % MOD;
a[rt].mul = (a[rt << 1].mul * a[(rt << 1) | 1].mul) % MOD;
下面是AC代码:
#include <cstdio>
using namespace std;
const int MAXN = 100005;
const int MOD = 10007;
typedef long long _long;
struct Node {
int l, r;
_long all, lseg, rseg, mul;
} a[MAXN * 3];
int n, q;
void pushUp(int rt) {
a[rt].all = (a[rt << 1].all + a[(rt << 1) | 1].all + a[rt << 1].rseg * a[(rt << 1) | 1].lseg) % MOD;
a[rt].lseg = (a[rt << 1].lseg + a[rt << 1].mul * a[(rt << 1) | 1].lseg) % MOD;
a[rt].rseg = (a[(rt << 1) | 1].rseg + a[(rt << 1) | 1].mul * a[rt << 1].rseg) % MOD;
a[rt].mul = (a[rt << 1].mul * a[(rt << 1) | 1].mul) % MOD;
}
void build(int rt, int l, int r) {
a[rt].l = l;
a[rt].r = r;
if (l == r) {
a[rt].all = a[rt].lseg = a[rt].rseg = a[rt].mul = 0;
return ;
}
int mid = (l + r) >> 1;
build(rt << 1, l, mid);
build((rt << 1) | 1, mid + 1, r);
pushUp(rt);
}
void update(int rt, int pos, long val) {
if (a[rt].l == pos && a[rt].r == pos) {
a[rt].all = a[rt].lseg = a[rt].rseg = a[rt].mul = val;
return ;
}
int mid = (a[rt].l + a[rt].r) >> 1;
if (pos <= mid) {
update(rt << 1, pos, val);
} else {
update((rt << 1) | 1, pos, val);
}
pushUp(rt);
}
int main() {
while (scanf("%d%d", &n, &q) != EOF) {
build(1, 1, n);
while (q--) {
int pos;
_long x;
scanf("%d%lld", &pos, &x);
update(1, pos, x % MOD);
printf("%lld\n", a[1].all);
}
}
return 0;
}