[bzoj5039] [Jsoi2014]序列维护

题目

传送门

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define ll long long
using namespace std;
const int maxn=1e5+10;
ll n,m,p,a[maxn<<2],add[maxn<<2],sum[maxn<<2],mul[maxn<<2];

void pushup(ll rt)
{
    sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%p;
//  printf("up: rt:%lld  %lld \n",rt,sum[rt]);
}
void pushdown(ll rt,ll ln,ll rn)
{
//  printf("down %lld %lld %lld \n",rt,ln,rn);
    if (mul[rt]!=1)
    {
        mul[rt<<1]=(mul[rt<<1]*mul[rt])%p;
        mul[rt<<1|1]=(mul[rt<<1|1]*mul[rt])%p;
        add[rt<<1]=(add[rt<<1]*mul[rt])%p;
        add[rt<<1|1]=(add[rt<<1|1]*mul[rt])%p;
        sum[rt<<1]=(sum[rt<<1]*mul[rt])%p;
        sum[rt<<1|1]=(sum[rt<<1|1]*mul[rt])%p;
        mul[rt]=1;
    }
    if (add[rt])
    {
        add[rt<<1]=(add[rt<<1]+add[rt])%p;
        add[rt<<1|1]=(add[rt<<1|1]+add[rt])%p;
        sum[rt<<1]=(sum[rt<<1]+add[rt]*ln)%p;
        sum[rt<<1|1]=(sum[rt<<1|1]+add[rt]*rn)%p;
        add[rt]=0;
    }
}

void build_tree(ll rt,ll l,ll r)
{   
    mul[rt]=1; add[rt]=0;
    if (l==r) {sum[rt]=a[l]; return;}
    ll mid=(l+r)>>1;
    build_tree(rt<<1,l,mid);
    build_tree(rt<<1|1,mid+1,r);
    pushup(rt);
}

void change(ll L,ll R,ll C,ll l,ll r,ll rt)//add
{
    if (L<=l && r<=R)
    {
        add[rt]+=C; add[rt]%=p;
        sum[rt]=(sum[rt]+C*(r-l+1))%p;
//      printf("change: %lld %lld %lld\n",add[rt],mul[rt],sum[rt]);
        return;
    }
    ll mid=(l+r)>>1;
    pushdown(rt,mid-l+1,r-mid);
    if (L<=mid) change(L,R,C,l,mid,rt<<1);
    if (R>mid) change(L,R,C,mid+1,r,rt<<1|1);
    pushup(rt);
}

void update(ll L,ll R,ll C,ll l,ll r,ll rt)//mul
{
    if (L<=l && r<=R)
    {
        sum[rt]=(sum[rt]*C)%p;
        mul[rt]=(mul[rt]*C)%p;
        add[rt]=(add[rt]*C)%p;
//      printf("update:%lld %lld %lld\n",add[rt],mul[rt],sum[rt]);
        return;
    }
    ll mid=(l+r)>>1;
    pushdown(rt,mid-l+1,r-mid);
    if (L<=mid) update(L,R,C,l,mid,rt<<1);
    if (R>mid) update(L,R,C,mid+1,r,rt<<1|1);
    pushup(rt);
}

ll ques(ll L,ll R,ll l,ll r,ll rt)
{
    if (L<=l && r<=R)
    {
//      printf("ques %lld %lld %lld\n",add[rt],mul[rt],sum[rt]); 
        return sum[rt];
    }
    ll mid=(l+r)>>1; ll ans=0;
    pushdown(rt,mid-l+1,r-mid);
    if (L<=mid) ans+=ques(L,R,l,mid,rt<<1); ans%=p;
    if (R>mid) ans+=ques(L,R,mid+1,r,rt<<1|1);
    return ans%p;
}

int main()
{
    scanf("%lld%lld",&n,&p);
    for (int i=1; i<=n; i++) scanf("%lld",&a[i]); scanf("%lld",&m); 
    build_tree(1,1,n);
//  for (ll i=1; i<=n*2; i++) printf("%lld %lld %lld\n",add[i],mul[i],sum[i]);
    for (ll i=1; i<=m; i++)
    {
        ll opt,x,y,z;
        scanf("%lld",&opt);
        if (opt==1)
        {
            scanf("%lld%lld%lld",&x,&y,&z);
            update(x,y,z,1,n,1);
        }
        else if (opt==2)
        {
            scanf("%lld%lld%lld",&x,&y,&z);
            change(x,y,z,1,n,1);
        }
        else if (opt==3)
        {
            scanf("%lld%lld",&x,&y);
            printf("%lld\n",ques(x,y,1,n,1)%p);
        }
    }
    return 0;
}

总结

水题也有必要说一下
这么水的题还要打1h+,频繁写错:
1. 乘的pushdown操作只需要乘上mul[rt],理解乘法优先原则
2. pushdown 调用的时候又mid-l+1
3. 写了一个change,粘到update没改change又GG
4. 一怒之下int都换成ll
5.pushup里面mod一下在B站上就A了
6. 以后pushdown可以使用for i=0…1枚举左右儿子减少代码量,加法和乘法放在一起写也行
7. 两个程序放在一起输出是调试的好方法

注意细节!写错了花大量时间用来调试就不值得了
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值