hihocoder-1116 : 計算 (線段樹區間合併)
阿新 • • 發佈:2018-11-22
描述
現在有一個有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
#include <stdio.h> #include <string.h> #include <ctime> #include <stack> #include <string> #include <algorithm> #include <iostream> #include <cmath> #include <map> #include <queue> #include <vector> using namespace std; #define LL long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lowbit(x) (x&-x) #define mem(x,a) memset(x,a,sizeof(x)) const int maxn = 5e5 + 5; const int INF = 0x3f3f3f3f; const int mod = 10007; int ans[maxn], sum[maxn], lbd[maxn], rbd[maxn]; int readint(){ int ret = 0, sgn = 1; char c = getchar(); while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') { ret = ret * 10 + c - '0'; } return ret*sgn; } void pushUp(int rt) { int ls = rt << 1, rs = rt << 1 | 1; sum[rt] = (sum[ls] * sum[rs]) % mod; lbd[rt] = (lbd[ls] + sum[ls] * lbd[rs]) % mod; rbd[rt] = (rbd[rs] + sum[rs] * rbd[ls]) % mod; ans[rt] = ((ans[ls] + ans[rs]) + (lbd[rs] * rbd[ls]) % mod) % mod; } void update(int x, int c, int l, int r, int rt) { if (l == r) { ans[rt] = sum[rt] = lbd[rt] = rbd[rt] = c; return; } int m = (l + r) >> 1; if (x <= m) update(x, c, lson); else update(x, c, rson); pushUp(rt); } int main() { int n, q; while (scanf("%d%d", &n, &q) != EOF) { mem(ans, 0); mem(lbd, 0); mem(rbd, 0); mem(sum, 0); while (q--) { int x = readint(); int c = readint() % mod; update(x, c, 1, n, 1); printf("%d\n", ans[1]); } } return 0; }