hihoCoder - 1116 - 計算 (線段樹)

計算

題目傳送:#1116 : 計算

這裏說下sum,pre,suf,ji數組的含義:

sum:所求答案
pre:所有前綴積之和
suf:所有後綴積之和
ji:區間內所有數之積

以一個例子說明:

比如我們現在正在合併區間{3,4},{2,5}

而區間{3,4}所表示的

sum1=3 + 4 + 3 * 4 = 19
pre1 = 3 + 3 * 4 = 12
suf1 = 3 * 4 + 4 = 16
ji1 = 3 * 4 = 12

而區間{2,5}

sum2 = 2 + 5 + 2 * 5 = 17
pre2 = 2 + 2 * 5 = 12
suf2 = 2 * 5 + 5 = 15
ji2 = 2 * 5 = 10

合併的時候:

sum = sum1 + sum2 + 3 * 4 * 2 + 3 * 4 * 2 * 5 + 4 * 2 + 4 * 2 * 5
即sum = sum1 + sum2 + suf1 * pre2

不過也要同時記得更新ji,pre和suf數組

AC代碼:

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <sstream>
#include <utility>
#include <iostream>
#include <algorithm>
#include <functional>
#define LL long long
#define INF 0x7fffffff
using namespace std;

#define MOD 10007

int n, q;

const int maxn = 100005;
int sum[maxn << 2];//此節點所表示區間內的所有子序列的乘積之和,即輸出答案爲sum[1]
int ji[maxn << 2];//此節點所表示區間內各個數之積
int pre[maxn << 2];//此節點所表示的區間處於合併時的後綴時所對合並後的區間的貢獻
int suf[maxn << 2];//此節點所表示的區間處於合併時的前綴時所對合並後的區間的貢獻

void pushup(int rt, int m) {
    ji[rt] = ji[rt << 1] * ji[rt << 1 | 1] % MOD;
    sum[rt] = (sum[rt << 1] + sum[rt << 1 | 1] + suf[rt << 1] * pre[rt << 1 | 1]) % MOD;
    pre[rt] = (pre[rt << 1] + ji[rt << 1] * pre[rt << 1 | 1]) % MOD;
    suf[rt] = (suf[rt << 1 | 1] + ji[rt << 1 | 1] * suf[rt << 1]) % MOD;
}

void build(int rt, int l, int r) {
    sum[rt] = 0;
    pre[rt] = 0;
    suf[rt] = 0;
    ji[rt] = 0;
    if(r == l) {
        return;
    }
    int mid = (l + r) >> 1;
    build(rt << 1, l, mid);
    build(rt << 1 | 1, mid + 1, r); 
}

void update(int rt, int l ,int r, int p, int x) {
    if(l == r && l == p) {
        sum[rt] = x % MOD;
        pre[rt] = x % MOD;
        suf[rt] = x % MOD;
        ji[rt] = x % MOD;
        return;
    }
    int mid = (l + r) >> 1;
    if(p <= mid) update(rt << 1, l, mid, p, x);
    else update(rt << 1 | 1, mid + 1, r, p, x);
    pushup(rt, r - l + 1);
}

int main() {
    scanf("%d %d", &n, &q);
    build(1, 1, n);
    for(int i = 0; i < q; i ++) {
        int p, x;
        scanf("%d %d", &p, &x); 
        update(1, 1, n, p, x);
        printf("%d\n", sum[1]);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章