其实一开始拿到这一道题把我吓到了,09年的题居然是裸的线段树?怀着半信半疑的态度写了一份,居然过了,qaq
然后第一份代码不知道哪里指针越界了,变量会莫名其妙的在其他地方改变,被迫把所有的int型改成long long强制重新分配内存,然后,long long嘛 时限4000+
维护两个lazy标记一个记录乘一个记录加,然后用手摸你一下改变的过程,然后利用乘法分配率,每次乘的同时还要修改加,每次修改加的时候就只修改加,下方标记的时候先乘再加,最后不知道数据有没有0的,反正保险用一个vis标记修改
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 200020
#define LL long long
#define ls u<<1,l,mid
#define rs u<<1|1,mid+1,r
using namespace std;
LL n,m,p;
struct node{
LL l,r,sum,lazy1,lazy2,vis1,vis2;//lazy1维护乘法 lazy2 维护加法
}nod[maxn*4];
void push_up(LL u){nod[u].sum=(nod[u<<1].sum+nod[u<<1|1].sum)%p;}
void push_down(LL u){
if(nod[u].vis1==0&&nod[u].vis2==0)return;
LL add1=nod[u].lazy1,add2=nod[u].lazy2;LL ll=u<<1,rr=u<<1|1;
if(nod[u].vis1)nod[ll].vis1=nod[rr].vis1=1;
if(nod[u].vis2 )nod[ll].vis2=nod[rr].vis2=1;
nod[ll].lazy1=(nod[ll].lazy1*add1)%p,nod[rr].lazy1=(nod[rr].lazy1*add1)%p;
nod[ll].lazy2=(nod[ll].lazy2*add1+add2)%p,nod[rr].lazy2=(nod[rr].lazy2*add1+add2)%p;
nod[ll].sum=(nod[ll].sum*add1+add2*(nod[ll].r-nod[ll].l+1))%p,nod[rr].sum=(nod[rr].sum*add1+add2*(nod[rr].r-nod[rr].l+1))%p;
nod[u].lazy1=1,nod[u].lazy2=0,nod[u].vis1=nod[u].vis2=0;
}
void build(LL u,LL l,LL r){
nod[u].vis1=nod[u].vis2=0,nod[u].l=l,nod[u].r=r;nod[u].lazy1=1,nod[u].lazy2=0;
if(l==r){scanf("%lld",&nod[u].sum);return;}
LL mid=l+r>>1;
build(ls),build(rs);
push_up(u);
}
void update(LL u,LL l,LL r,LL x,LL y,LL add,LL pos){
if(l==x&&r==y){
if(pos==1)nod[u].lazy1=(nod[u].lazy1*add)%p,nod[u].lazy2=(nod[u].lazy2*add)%p,nod[u].sum=(nod[u].sum*add)%p,nod[u].vis1=1;
else nod[u].lazy2=(nod[u].lazy2+add)%p,nod[u].sum=(nod[u].sum+add*(nod[u].r-nod[u].l+1))%p,nod[u].vis2=1;
return;
}
LL mid=l+r>>1;
push_down(u);
if(x>mid)update(rs,x,y,add,pos);
else if(y<=mid)update(ls,x,y,add,pos);
else update(ls,x,mid,add,pos),update(rs,mid+1,y,add,pos);
push_up(u);
}
LL query(LL u,LL l,LL r,LL x,LL y){
if(x==l&&r==y)return nod[u].sum;
LL mid=l+r>>1;
push_down(u);
if(x>mid)return query(rs,x,y)%p;
else if(y<=mid)return query(ls,x,y)%p;
else return (query(ls,x,mid)+query(rs,mid+1,y))%p;
}
int main(){
scanf("%lld%lld",&n,&p);
build(1,1,n);
scanf("%lld",&m);
for(LL pos,a,b,c,i=1;i<=m;i++){
scanf("%lld%lld%lld",&pos,&a,&b);
if(pos==1){
scanf("%lld",&c);update(1,1,n,a,b,c,1);
}else if(pos==2){
scanf("%lld",&c);update(1,1,n,a,b,c,2);
}else{
printf("%lld\n",query(1,1,n,a,b));
}
}
return 0;
}