洛谷P2023 [AHOI2009]维护序列 (BZOJ1798)

来源:互联网 发布:白金数据 高清 网盘 编辑:程序博客网 时间:2024/05/29 09:59

线段树

洛谷题目传送门
BZOJ题目传送门

裸的双Tag线段树。。。(不过我都没打过双Tag的线段树)
BZOJMLE说我TLE。。。害我郁闷了半天。。。
注意BZOJ只给64MB
还有就是一定要先乘后加
具体见注释

代码:

#include<cctype>#include<cstdio>#include<cstring>#include<algorithm>#define MAXN 150000using namespace std;typedef long long LL;//开LL保险一点struct tree{    LL l,r;    LL sum;}t[MAXN*4+5];LL n,m,MOD;LL a[MAXN+5],lazy1[MAXN*4+5],lazy2[MAXN*4+5];//1表示加,2表示乘inline char readc(){//fread读优    static char buf[100000],*l=buf,*r=buf;    if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);    if (l==r) return EOF; return *l++;}inline LL _read(){    LL num=0; char ch=readc();    while (!isdigit(ch)) ch=readc();    while (isdigit(ch)) { num=num*10+ch-48; ch=readc(); }    return num;}void build(LL l,LL r,LL num){//建树    t[num].l=l,t[num].r=r;    if (l==r){//给叶子结点赋值        t[num].sum=a[l];        return;    }    build(l,(l+r)/2,num*2);    build((l+r)/2+1,r,num*2+1);    t[num].sum=(t[num*2].sum+t[num*2+1].sum)%MOD;}void pushdown(LL num){//传Tag    if (lazy2[num]!=1){//先算乘法        (lazy2[num*2]*=lazy2[num])%=MOD;        (lazy2[num*2+1]*=lazy2[num])%=MOD;        t[num*2].sum=(t[num*2].sum*lazy2[num])%MOD;        t[num*2+1].sum=(t[num*2+1].sum*lazy2[num])%MOD;        (lazy1[num*2]*=lazy2[num])%=MOD;        (lazy1[num*2+1]*=lazy2[num])%=MOD;        lazy2[num]=1;//1    }    if (lazy1[num]){//再算加法        (lazy1[num*2]+=lazy1[num])%=MOD;        (lazy1[num*2+1]+=lazy1[num])%=MOD;        (t[num*2].sum+=((t[num*2].r-t[num*2].l+1)*lazy1[num])%MOD)%=MOD;        (t[num*2+1].sum+=((t[num*2+1].r-t[num*2+1].l+1)*lazy1[num])%MOD)%=MOD;        lazy1[num]=0;//0    }}void nsrt(LL l,LL r,LL w,bool flag,LL num){//插入(修改)    if (t[num].l>=l&&t[num].r<=r){        if (!flag){//如果是乘操作            t[num].sum=(t[num].sum*w)%MOD;            lazy2[num]=(lazy2[num]*w)%MOD;            lazy1[num]=(lazy1[num]*w)%MOD;//别忘了给加Tag乘        }        else{            t[num].sum=(t[num].sum+((t[num].r-t[num].l+1)*w)%MOD)%MOD;            lazy1[num]=(lazy1[num]+w)%MOD;        }        return;    }    if (t[num].l>r||t[num].r<l) return;    if (lazy1[num]||lazy2[num]!=1)        pushdown(num);    nsrt(l,r,w,flag,num*2);    nsrt(l,r,w,flag,num*2+1);    t[num].sum=(t[num*2].sum+t[num*2+1].sum)%MOD;}LL srch(LL l,LL r,LL num){    if (t[num].l>=l&&t[num].r<=r)         return t[num].sum;    if (t[num].r<l||t[num].l>r)         return 0;    if (lazy1[num]||lazy2[num]!=1)        pushdown(num);    LL x=srch(l,r,num*2);    LL y=srch(l,r,num*2+1);    return (x+y)%MOD;}int main(){    n=_read(),MOD=_read();    for (LL i=1;i<=n;i++)        a[i]=(_read())%MOD;    m=_read();    for (LL i=1;i<=MAXN*4;i++)        lazy2[i]=1;    build(1,n,1);    while (m--){        LL flag=_read();        switch (flag){            case 1:{                LL l=_read(),r=_read(),w=_read();                nsrt(l,r,w,0,1);                break;            }            case 2:{                LL l=_read(),r=_read(),w=_read();                nsrt(l,r,w,1,1);                break;            }            default:{                LL l=_read(),r=_read();                printf("%d\n",srch(l,r,1));                break;            }        }    }    return 0;}
原创粉丝点击