rt,先放代码
d数组是原数组,t数组是树,add和pls是加法和乘法的lazytag
我感觉在maketag或pushdown函数那里有些问题,但是没有看出来是哪里的问题,希望有神仙可以帮忙调一下QAQ
//------------------------
//Online Judge : Luogu
//By : KS_tips_CN
//Subject :
//------------------------
//#include<bits/stdc++.h>
//#include<map>
//#include<stack>
//#include<list>
//#include<set>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
#define ll long long
#define reg register int
#define gc getchar()
#define MAXN 100010
#define MOD
using namespace std;
inline ll read( void ) ;
int n,m,mod;
ll t[MAXN*4],d[MAXN],lazy_add[MAXN*4],lazy_pls[MAXN*4];
inline void build( int x , int l , int r ){
if( l == r ){
t[x] = d[l];
t[x] %= mod;
return ;
}
int mid = ( l + r ) >> 1 ;
build( x*2 , l , mid );
build( x*2+1 , mid+1 , r );
t[x] = t[x*2] + t[x*2+1] ;
t[x] %= mod;
}
//建树
inline bool In_Range( int l , int r , int L , int R ){
if( L >= l && R <= r ) return 1;//如果右区间在左区间内,返回1
return 0;
}
inline bool Out_Range( int l , int r , int L , int R ){
if( l > R || r < L ) return 1;
return 0;
}
inline void make_tag( int x , int l , int r , ll add , ll pls ){
//如果先推add,那么add在每次下推都会被pls一遍,所以先pls
if( !lazy_pls[x] ) lazy_pls[x] = 1 ;
t[x] = ( t[x] * pls ) % mod ;
lazy_pls[x] = ( lazy_pls[x] * pls ) % mod ;
lazy_add[x] = ( lazy_add[x] * pls ) % mod ;
//修改这个节点的值和这个节点所承受的tag,包括乘法和加法
t[x] = ( t[x] + (r-l+1) * add ) % mod ;
lazy_add[x] = ( lazy_add[x] + add ) % mod ;
}
inline void pushdown( int x , int l , int r ){
int mid = ( l + r ) >> 1 ;
make_tag( x*2 , l , mid , lazy_add[x] , lazy_pls[x] );
make_tag( x*2+1 , mid+1 , r , lazy_add[x] , lazy_pls[x] );
lazy_add[x] = 0 ;
lazy_pls[x] = 1 ;
}
//接下来我们按照正常方法写三个函数,分别是加法,乘法,查询
inline void add( int x , int l , int r , int L , int R , ll num ){
//当前在序号为x的[l,r]区间 为目标区间[L,R] 加上num
if( In_Range(L,R,l,r) ) make_tag( x , l , r , num , 1 );
else {
if( !Out_Range(L,R,l,r) ){
pushdown(x,l,r);
int mid = ( l + r ) >> 1 ;
add( x*2 , l , mid , L , R , num );
add( x*2+1 , mid+1 , r , L , R , num );
t[x] = t[x*2] + t[x*2+1] ;
t[x] %= mod;
}
}
}
inline void plus_( int x , int l , int r , int L , int R , ll num ){
if( In_Range(L,R,l,r) ) make_tag( x , l , r , 0 , num );
else {
if( !Out_Range(L,R,l,r) ){
pushdown(x,l,r);
int mid = ( l + r ) >> 1 ;
plus_( x*2 , l ,mid , L , R , num );
plus_( x*2+1 , mid+1 , r , L , R , num );
t[x] = t[x*2] + t[x*2+1] ;
t[x] %= mod;
}
}
}
inline ll search( int x , int l , int r , int L , int R ){
if( In_Range(L,R,l,r) ) return t[x];
else if( Out_Range(L,R,l,r) ) return 0;
else {
pushdown(x,l,r);
int mid = ( l + r ) >> 1 ;
return ( search( x*2 , l , mid , L , R ) + search( x*2+1 , mid+1 , r , L , R ) ) % mod ;
}
}
int main( void ) {
n = read();//
m = read();//操作数量
mod = read();//模数
for( reg i = 1 ; i <= n ; i++ ) d[i] = read();
build(1,1,n);
int a,b,c;
ll d;
for( reg i = 1 ; i <= m ; i++ ){
a = read();
b = read();
c = read();
if( a == 1 ){
cin >> d ;
plus_(1,1,n,b,c,d);
}
else if( a == 2 ){
cin >> d ;
add(1,1,n,b,c,d);
}
else {
cout << search(1,1,n,b,c) << endl ;
}
}
return 0;
}
inline ll read( void ) {
ll x = 0 , f = 0 ;
char ch = gc ;
while( !isdigit( ch ) )
f |= ( ch == '-' ) , ch = gc ;
while( isdigit( ch ) )
x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ) , ch = gc ;
return f ? -x : x ;
}