题解 P3373 【【模板】线段树 2】
接3372我题解的板子修改,依旧参考will大佬和CSDN:http://www.cnblogs.com/TenosDoIt/p/3453089.html
关于3373,有几个细节要提一下。
1:tag2的初始值为1;
2:pushdown里先tag2后tag1(先乘后加);
3:对tag2进行push需要先把tag1*tag2,tag2*tag2,val*tag2,最后别忘了tag2=1;
4:tag2不需要乘区间;
下面是code:
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
long long val,lazytag,lazytag2;
}segTree[100000*4+5];
long long a[100005];
long long n,m,t,x,y,k,p;
void build(int root,long long arr[],int istart,int iend){//建树
segTree[root].lazytag=0;
segTree[root].lazytag2=1;
if(istart==iend){
segTree[root].val=arr[istart];
}else{
int mid=(istart+iend)/2;
build(root*2,arr,istart,mid);
build(root*2+1,arr,mid+1,iend);
segTree[root].val=segTree[root*2].val+segTree[root*2+1].val;
}
}
void pushDown(int root,int start,int end){//插入懒标记
**if(segTree[root].lazytag2!=1){**
segTree[root*2].lazytag=(segTree[root*2].lazytag*segTree[root].lazytag2)%p;
segTree[root*2+1].lazytag=(segTree[root*2+1].lazytag*segTree[root].lazytag2)%p;
segTree[root*2].lazytag2=(segTree[root*2].lazytag2*segTree[root].lazytag2)%p;
segTree[root*2+1].lazytag2=(segTree[root*2+1].lazytag2*segTree[root].lazytag2)%p;
int midd=(end+start)/2;
segTree[root*2].val=(segTree[root*2].val*(segTree[root].lazytag2))%p;
segTree[root*2+1].val=(segTree[root*2+1].val*(segTree[root].lazytag2))%p;
segTree[root].lazytag2=1;
}
if(segTree[root].lazytag!=0){
segTree[root*2].lazytag+=segTree[root].lazytag;
segTree[root*2+1].lazytag+=segTree[root].lazytag;
int mid=(end+start)/2;
segTree[root*2].val+=segTree[root].lazytag*(mid-start+1);
segTree[root*2+1].val+=segTree[root].lazytag*(end-mid);
segTree[root].lazytag=0;
}
}
long long query(int root,int nstart,int nend,int qstart,int qend){//查询区间
if(qstart>nend||qend<nstart){
return 0;
}if(qstart<=nstart&&qend>=nend){
return segTree[root].val;
}
pushDown(root,nstart,nend);
int mid=(nstart+nend)/2;
return query(root*2,nstart,mid,qstart,qend)+query(root*2+1,mid+1,nend,qstart,qend);
}
void update(int root,int nstart,int nend,int ustart,int uend,int addval){//赋值
if(ustart>nend||uend<nstart){
return;
}if(ustart<=nstart&&uend>=nend){
segTree[root].lazytag+=addval;
segTree[root].val+=addval*(nend-nstart+1);
return;
}
pushDown(root,nstart,nend);
int mid=(nstart+nend)/2;
update(root*2,nstart,mid,ustart,uend,addval);
update(root*2+1,mid+1,nend,ustart,uend,addval);
segTree[root].val=segTree[root*2].val+segTree[root*2+1].val;
}
**void tupdate(int root,int nstart,int nend,int ustart,int uend,int addval){//赋值(chengfa**
if(ustart>nend||uend<nstart){
return;
}if(ustart<=nstart&&uend>=nend){
segTree[root].lazytag=(segTree[root].lazytag*addval)%p;
segTree[root].lazytag2=(segTree[root].lazytag2*addval)%p;
segTree[root].val=(segTree[root].val*addval)%p;
return;
}
pushDown(root,nstart,nend);
int mid=(nstart+nend)/2;
tupdate(root*2,nstart,mid,ustart,uend,addval);
tupdate(root*2+1,mid+1,nend,ustart,uend,addval);
segTree[root].val=segTree[root*2].val+segTree[root*2+1].val;
}
int main(){
scanf("%lld%lld%lld",&n,&m,&p);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
build(1,a,1,n);
for(int i=1;i<=m;i++){
scanf("%lld",&t);
if(t==2){
scanf("%lld%lld%lld",&x,&y,&k);
update(1,1,n,x,y,k);
}if(t==3){
scanf("%lld%lld",&x,&y);
printf("%lld\n",query(1,1,n,x,y)%p);
}if(t==1){
scanf("%lld%lld%lld",&x,&y,&k);
tupdate(1,1,n,x,y,k);
}
}
return 0;
}