bzoj1798

线段树基础题

看到有大佬写了splay.....orz%%

二维标记下传,注意下传的顺序就好了

/**************************************************************

    Problem: 1798

    User: syh0313

    Language: C++

    Result: Accepted

    Time:4836 ms

    Memory:17700 kb

****************************************************************/

 

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <string>

#define lch a[n].lc

#define rch a[n].rc

using namespace std;

const int maxn=100010;

int n,m,root,topt;

long long v[maxn],mo;

struct da{int lc,rc,l,r;long long mul,add,sum;}a[4*maxn];

inline void updata(int n){a[n].sum=(a[lch].sum+a[rch].sum)%mo;}

void build_tree(int &n,int l,int r)

{

    n=++topt; a[n].add=0; a[n].mul=1; a[n].sum=0; a[n].l=l; a[n].r=r;

    if (l==r) {a[n].sum=v[l]%mo; return;}

    int mid=(l+r)>>1;

    build_tree(lch,l,mid); build_tree(rch,mid+1,r);

    updata(n);

}

void pushdown(int n)

{

    if (a[n].mul!=1)

    {

        a[lch].sum=a[lch].sum*a[n].mul%mo;

        a[lch].add=a[lch].add*a[n].mul%mo;

        a[lch].mul=a[lch].mul*a[n].mul%mo;

        a[rch].sum=a[rch].sum*a[n].mul%mo;

        a[rch].add=a[rch].add*a[n].mul%mo;

        a[rch].mul=a[rch].mul*a[n].mul%mo;

        a[n].mul=1;

    }

    if (a[n].add)

    {

        a[lch].add=(a[lch].add+a[n].add)%mo;

        a[lch].sum=(a[lch].sum+a[n].add*(a[lch].r-a[lch].l+1)%mo)%mo;

        a[rch].add=(a[rch].add+a[n].add)%mo;

        a[rch].sum=(a[rch].sum+a[n].add*(a[rch].r-a[rch].l+1)%mo)%mo;

        a[n].add=0;

    }

}

void tree_add(int n,int L,int R,int l,int r,long long k)

{

    if (L==l && R==r)

    {

        a[n].sum=(a[n].sum+k*(r-l+1)%mo)%mo;

        a[n].add=(a[n].add+k)%mo;

        return;

    }

    int mid=(L+R)>>1; pushdown(n);

    if (r<=mid) tree_add(lch,L,mid,l,r,k);

    else if (l>=mid+1) tree_add(rch,mid+1,R,l,r,k);

    else tree_add(lch,L,mid,l,mid,k),tree_add(rch,mid+1,R,mid+1,r,k);

    updata(n);

}

void tree_mul(int n,int L,int R,int l,int r,long long k)

{

    if (L==l && R==r)

    {

        a[n].sum=a[n].sum*k%mo;

        a[n].add=a[n].add*k%mo;

        a[n].mul=a[n].mul*k%mo;

        return;

    }

    int mid=(L+R)>>1; pushdown(n);

    if (r<=mid) tree_mul(lch,L,mid,l,r,k);

    else if (l>=mid+1) tree_mul(rch,mid+1,R,l,r,k);

    else tree_mul(lch,L,mid,l,mid,k),tree_mul(rch,mid+1,R,mid+1,r,k);

    updata(n);

}

long long qury(int n,int L,int R,int l,int r)

{

    if (L==l && R==r) return a[n].sum;

    int mid=(L+R)>>1; pushdown(n);

    if (r<=mid) return qury(lch,L,mid,l,r);

    else if (l>=mid+1) return qury(rch,mid+1,R,l,r);

    else return (qury(lch,L,mid,l,mid)+qury(rch,mid+1,R,mid+1,r))%mo;

    updata(n);

}

int main()

{

    scanf("%d%lld",&n,&mo);

    for (int i=1;i<=n;i++) scanf("%lld",&v[i]);

    build_tree(root,1,n);

    scanf("%d",&m);

    while (m--)

    {

        int ff,xx,yy; long long kk; scanf("%d%d%d",&ff,&xx,&yy);

        if (ff==1) scanf("%lld",&kk),tree_mul(root,1,n,xx,yy,kk);

        else if (ff==2) scanf("%lld",&kk),tree_add(root,1,n,xx,yy,kk);

        else if (ff==3) printf("%lld\n",qury(root,1,n,xx,yy));

    }

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值