[BZOJ 1798][Ahoi2009]Seq 維護序列seq

先乘後加線段樹

就是pushdown的時候要在訪問之前進行

推薦自己寫plus和mul

這樣就不用爲%m困擾了

%%%

不管爲什麼放在前面就好啦


#include 
#include 
#include 
#include 
#define maxn 100010
using namespace std;
typedef long long ll;
int n, opt, a[maxn];
ll m;

struct Node{
    int l, r;
    ll s, m, a;
}t[maxn << 3];
#define lc id<<1
#define rc id<<1|1
void pushdown(int id){
    int l = t[id].l, r = t[id].r, mid = l + r >> 1;
    t[lc].s = (t[lc].s * t[id].m + t[id].a * (mid - l + 1)) % m;
    t[rc].s = (t[rc].s * t[id].m + t[id].a * (r - mid)) % m;
    t[lc].m = t[lc].m * t[id].m % m;
    t[rc].m = t[rc].m * t[id].m % m;
    t[lc].a = (t[lc].a * t[id].m + t[id].a) % m;
    t[rc].a = (t[rc].a * t[id].m + t[id].a) % m;
    t[id].m = 1, t[id].a = 0;
}

void pushup(int id){t[id].s = (t[lc].s + t[rc].s) % m;}

void build(int id, int l, int r){
    t[id].l = l, t[id].r = r, t[id].m = 1, t[id].a = 0;
    if(l == r){
        t[id].s = a[l] % m;
        return;
    }
    int mid = l + r >> 1;
    build(lc, l, mid);
    build(rc, mid+1, r);
    pushup(id);
}

ll ask(int id, int l, int r){
    pushdown(id);
    if(t[id].l == l && t[id].r == r)
        return t[id].s;
    int mid = t[id].l + t[id].r >> 1;
    if(r <= mid)return ask(lc, l, r);
    if(l > mid)return ask(rc, l, r);
    return (ask(lc, l, mid) + ask(rc, mid+1, r)) % m;
}

void Mul(int id, int l, int r, int c){
    pushdown(id);
    if(t[id].l == l && t[id].r == r){
        t[id].m = t[id].m * c % m;
        t[id].s = t[id].s * c % m;
        return;
    }
    int mid = t[id].l + t[id].r >> 1;
    if(r <= mid) Mul(lc, l, r, c);
    else if(l > mid) Mul(rc, l, r, c);
    else{
        Mul(lc, l, mid, c);
        Mul(rc, mid+1, r, c);
    }
    pushup(id);
}

void Plus(int id, int l, int r, int c){
    pushdown(id);
    if(t[id].l == l && t[id].r == r){
        t[id].a += c;t[id].a %= m;
        t[id].s += 1ll * (r - l + 1) * c;t[id].s %= m;
        return;
    }
    int mid = t[id].l + t[id].r >> 1;
    if(r <= mid) Plus(lc, l, r, c);
    else if(l > mid) Plus(rc, l, r, c);
    else{
        Plus(lc, l, mid, c);
        Plus(rc, mid+1, r, c);
    }
    pushup(id);
}

int main(){
    //freopen("seq.in", "r", stdin);
    //freopen("seq.out", "w", stdout);
    scanf("%d%lld", &n, &m);
    for(int i = 1; i <= n; i ++)
        scanf("%d", &a[i]);
    build(1, 1, n);
    scanf("%d", &opt);
    int type, l, r, c;
    for(int i = 1; i <= opt; i ++){
        scanf("%d", &type);
        if(type == 3){
            scanf("%d%d", &l, &r);
            printf("%lld\n", ask(1, l, r) % m);
            continue;
        }
        scanf("%d%d%d", &l, &r, &c);
        if(type == 1)Mul(1, l, r, c);
        else Plus(1, l, r, c);
    }
    //while(true);
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章