BZOJ1798——[Ahoi2009]Seq维护序列seq

1、题目大意:区间修改乘法操作和加法操作,求区间和
2、分析:为了填补bzoj2631的坑还是写一发题解吧,首先呢,既然想要双标记,但是这两个标记之间又有着制约作用,所以要定义优先级,这个优先级就定义为乘法先,加法后吧。。。那个一个区间的标记无非就是乘a加b,那么重点就是如何下传标记了。首先儿子有两个标记c,d,父亲有两个标记a,b, 那么c就等于c乘a啦,而d等于d乘a加b(从操作的先后顺序考虑)很显然吧。于是问题就解决了
3、代码:( 当时的线段树姿势丑陋,求轻喷

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL long long
struct segment_tree{
    LL N, P;
    LL sum[1000000];
    LL clazy[1000000];
    LL jlazy[1000000];
    LL value[1000000];
    LL x, y, z;
    void build(LL l, LL r, LL o){
        if(l == r){
            clazy[o] = 1;
            jlazy[o] = 0;
            sum[o] = value[l];
            return;
        }
        int mid = (l + r) / 2;
        build(l, mid, 2 * o);
        build(mid + 1, r, 2 * o + 1);
        sum[o] = sum[2 * o] + sum[2 * o + 1]; sum[o] %= P;
        clazy[o] = 1;
        jlazy[o] = 0;
        return;
    }
    void updata(LL l, LL r, LL o){
        clazy[2 * o] *= clazy[o]; clazy[2 * o] %= P;
        jlazy[2 * o] *= clazy[o]; jlazy[2 * o] %= P;
        jlazy[2 * o] += jlazy[o]; jlazy[2 * o] %= P;
        clazy[2 * o + 1] *= clazy[o]; clazy[2 * o + 1] %= P;
        jlazy[2 * o + 1] *= clazy[o]; jlazy[2 * o + 1] %= P;
        jlazy[2 * o + 1] += jlazy[o]; jlazy[2 * o + 1] %= P;
        sum[o] = sum[o] * clazy[o] + jlazy[o] * (r - l + 1); sum[o] %= P;
        clazy[o] = 1;
        jlazy[o] = 0;
        return;
    }
    void add_c(LL l, LL r, LL o){
        updata(l, r, o);
        if(x > r || y < l) return;
        if(x <= l && r <= y){
            clazy[o] = z;
            updata(l, r, o);
            return;
        }
        LL mid = (l + r) / 2;
        add_c(l, mid, 2 * o);
        add_c(mid + 1, r, 2 * o + 1);
        sum[o] = sum[2 * o] + sum[2 * o + 1]; sum[o] %= P;
        return;
    }
    void add_j(LL l, LL r, LL o){
        updata(l, r, o);
        if(x > r || y < l) return;
        if(x <= l && r <= y){
            jlazy[o] = z;
            updata(l, r, o);
            return;
        }
        LL mid = (l + r) / 2;
        add_j(l, mid, 2 * o);
        add_j(mid + 1, r, 2 * o + 1);
        sum[o] = sum[2 * o] + sum[2 * o + 1]; sum[o] %= P;
        return;
    }
    LL query(LL l, LL r, LL o){
        updata(l, r, o);
        if(x > r || y < l) return 0;
        if(x <= l && r <= y) return sum[o];
        LL mid = (l + r) / 2;
        LL ret = 0;
        ret += query(l, mid, 2 * o); ret %= P;
        ret += query(mid + 1, r, 2 * o + 1); ret %= P;
        sum[o] = sum[2 * o] + sum[2 * o + 1]; sum[o] %= P;
        return ret; 
    }
} wt;
int main(){
    scanf("%lld%lld", &wt.N, &wt.P);
    for(LL i = 1; i <= wt.N; i ++){
        scanf("%lld", &wt.value[i]);
    }
    wt.build(1, wt.N, 1);
    LL q;
    scanf("%lld", &q);
    while(q --){
        LL a;
        scanf("%lld", &a);
        if(a == 1){
            scanf("%lld%lld%lld", &wt.x, &wt.y, &wt.z);
            wt.add_c(1, wt.N, 1);
        }
        else if(a == 2){
            scanf("%lld%lld%lld", &wt.x, &wt.y, &wt.z);
            wt.add_j(1, wt.N, 1);
        }
        else if(a == 3){
            scanf("%lld%lld", &wt.x, &wt.y);
            printf("%lld\n", wt.query(1, wt.N, 1));
        }
    }
    return 0;
} 


你可能感兴趣的:(线段树,bzoj,1798,AHOI2009,维护序列)