【AHOI2009】【BZOJ1798】Seq 维护序列seq(线段树模板,易错提醒)

problem

  • 给定一个长为n的序列,m次询问
  • 每次询问有3种操作
    1、一段区间全部乘一个值
    2、一段区间全部加一个值
    3、询问一段区间和%P

solution

不就一颗线段树么,看朕10分钟A掉。。。
30分钟过后:md我脑残了吧,连线段树都写不来了?还爆栈???
1小时过后:我靠,WA什么鬼,样例是水做的么?
2小时过后:什么垃圾题,还不让下数据。我用线段树模板题调。
3小时过后:朕今天就不信邪了!!!


线段树智障错法整理:
1、add,mul,query都要加pushdown。
2、和值有关的都开long long , query千万记得mod
3、递归的地方if是L不是l。
4、4倍空间、
5、调试:C++重载函数(参数不同可以同名),直接找个不同参数的复制过去调。
6、不行就重写!!!重写比调试快!!!!!10mins重写,1000mins调试?

codes

#include<iostream>
using namespace std;

struct SegmentTree{
    typedef long long LL;
    #define maxn 500010
    #define lch p<<1
    #define rch p<<1|1
    struct node{
        LL val, addmark, mulmark;
    }sgt[maxn<<2];
    int mod;

    void build(int p, int l, int r){
        sgt[p].addmark = 0, sgt[p].mulmark = 1;
        if(l == r){
            cin>>sgt[p].val;
            return ;
        }
        int mid = l+r>>1;
        build(lch,l,mid);
        build(rch,mid+1,r);
        sgt[p].val = (sgt[lch].val+sgt[rch].val)%mod;
        return ;
    }
    void pushdown(int p, int l, int r){
        if(sgt[p].addmark==0&&sgt[p].mulmark==1)return ;
        //父节点标记
        LL t1 = sgt[p].addmark, t2 = sgt[p].mulmark;
        sgt[p].addmark = 0, sgt[p].mulmark = 1;
        //维护标记
        int mid = l+r>>1;
        sgt[lch].mulmark *= t2, sgt[lch].mulmark %= mod;
        sgt[rch].mulmark *= t2, sgt[rch].mulmark %= mod;
        sgt[lch].addmark = (sgt[lch].addmark*t2+t1)%mod;
        sgt[rch].addmark = (sgt[rch].addmark*t2+t1)%mod;
        //更新值
        sgt[lch].val = (sgt[lch].val*t2+t1*(mid-l+1))%mod;
        sgt[rch].val = (sgt[rch].val*t2+t1*(r-mid))%mod;
        return ;
    }

    void add(int p, int l, int r, int L, int R, LL v){
        if(L<=l && r<=R){
            sgt[p].val += (r-l+1)*v;  
            sgt[p].val %= mod;
            sgt[p].addmark += v;
            sgt[p].addmark %= mod;
            return ;
        }
        pushdown(p,l,r);
        int mid = l+r>>1;
        if(L<=mid)add(lch,l,mid,L,R,v);//是L不是l
        if(R>mid)add(rch, mid+1, r,L,R,v);
        sgt[p].val = (sgt[lch].val+sgt[rch].val)%mod;
    }
    void times(int p, int l, int r, int L, int R, LL v){
        if(L<=l && r<=R){
            sgt[p].val *= v;
            sgt[p].val %= mod;
            sgt[p].mulmark *= v;
            sgt[p].mulmark %= mod;
            sgt[p].addmark *= v;
            sgt[p].addmark %= mod;
            return ;
        }
        pushdown(p,l,r);
        int mid = (l+r)/2;
        if(L<=mid)times(lch,l,mid,L,R,v);
        if(R>mid)times(rch,mid+1,r,L,R,v);
        sgt[p].val = (sgt[lch].val+sgt[rch].val)%mod;
    }

    LL query(int p, int l, int r, int L, int R){
        if(L<=l && r<=R)return sgt[p].val;
        pushdown(p,l,r);
        LL mid = l+r>>1, ans = 0;
        if(L<=mid)ans += query(lch,l,mid,L,R);
        if(R>mid)ans += query(rch,mid+1,r,L,R);
        return ans%mod;
    }
}sgt;

int main(){
    int n, m, q;
    cin>>n>>q;
    sgt.mod = q;
    sgt.build(1,1,n);
    cin>>m;
    for(int i = 1; i <= m; i++){
        int op, l, r, v;
        cin>>op;
        if(op==1){
            cin>>l>>r>>v;
            sgt.times(1,1,n,l,r,v);
        }else if(op==2){
            cin>>l>>r>>v;
            sgt.add(1,1,n,l,r,v);
        }else{
            cin>>l>>r;
            cout<<(sgt.query(1,1,n,l,r))<<'\n';
        }
    }
    return 0;
}
posted @ 2018-08-13 17:56  gwj1139177410  阅读(120)  评论(0编辑  收藏  举报
选择