已AC 但我线段树空间明明开了四倍 为什么N设置成100005过不了 要设置成400000才可以?
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<map>
#include<string.h>
#include<queue>
#define ll long long
#define debug cout<<"How badly it works!"<<endl;
using namespace std;
const int N=400005;
ll n,m,p;
struct node{
ll x,y,sum,lza,lzm;
}f[N<<2];
struct tree{
#define ls (r<<1)
#define rs ((r<<1)|1)
#define mid ((f[r].x+f[r].y)>>1)
void pushup(int r){
f[r].sum=f[ls].sum+f[rs].sum;
return;
}
void pushdown(int r){
f[ls].lza=(f[r].lza+f[ls].lza*f[r].lzm)%p;//孩子的加法lazy标记乘上父亲的乘法lazy标记
f[rs].lza=(f[r].lza+f[rs].lza*f[r].lzm)%p;
f[ls].lzm=(f[ls].lzm*f[r].lzm)%p;//孩子的乘法lazy标记直接乘以父亲的乘法lazy标记
f[rs].lzm=(f[rs].lzm*f[r].lzm)%p;
f[ls].sum=(f[ls].sum*f[r].lzm+f[r].lza*(f[ls].y-f[ls].x+1))%p;//sum整体乘上乘法lazy标记,再加上自己区间中数的个数乘以加法lazy标记
f[rs].sum=(f[rs].sum*f[r].lzm+f[r].lza*(f[rs].y-f[rs].x+1))%p;//(分开算的原因是之前加法lazy标记已经乘上父亲lazy标记了)
f[r].lza=0;//清空lazy标记
f[r].lzm=1;
return;
}
void init(int r,int x,int y){
f[r].lzm=1;
f[r].x=x,f[r].y=y;
if(x==y){
scanf("%lld",&f[r].sum);
return;
}
init(ls,x,mid);
init(rs,mid+1,y);
pushup(r);
}
void upd_add(int r,int k,int x,int y){
pushdown(r);//在点值更新之后下传lazy标记,如果下面更新时写的是k,则位置无影响
if(f[r].x>=x&&f[r].y<=y){
f[r].sum=(f[r].sum+(f[r].y-f[r].x+1)*k)%p;//注意这里的顺序,有影响
f[r].lza=(f[r].lza+k)%p;
return;
}
if(x<=mid){
upd_add(ls,k,x,y);
}
if(y>=mid+1){
upd_add(rs,k,x,y);
}
pushup(r);
}
void upd_mul(int r,int k,int x,int y){
pushdown(r);//在点值更新之后下传lazy标记,如果下面写的是k,则无影响
if(f[r].x>=x&&f[r].y<=y){
f[r].sum=(f[r].sum*k)%p;//注意这里的顺序
f[r].lzm=(f[r].lzm*k)%p;
return;
}
if(x<=mid){
upd_mul(ls,k,x,y);
}
if(y>=mid+1){
upd_mul(rs,k,x,y);
}
pushup(r);
}
ll query(int r,int x,int y){
pushdown(r);//位置无影响
if(f[r].x>=x&&f[r].y<=y){
return f[r].sum%p;
}
ll ans=0;
if(x<=mid){
ans+=query(ls,x,y);
ans%=p;
}
if(y>=mid+1){
ans+=query(rs,x,y);
ans%=p;
}
return ans;
}
}tr;
int main(){
scanf("%lld%lld%lld",&n,&m,&p);
tr.init(1,1,n);
for(int i=1;i<=m;i++){
int op,x,y,k;
scanf("%d",&op);
if(op==1){
scanf("%d%d%d",&x,&y,&k);
tr.upd_mul(1,k,x,y);
}
if(op==2){
scanf("%d%d%d",&x,&y,&k);
tr.upd_add(1,k,x,y);
}
if(op==3){
scanf("%d%d",&x,&y);
ll ans=tr.query(1,x,y);
printf("%lld\n",ans%p);
}
}
return 0;
}