题目
代码
#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. 两个程序放在一起输出是调试的好方法