두 세그먼트 트리 템플릿

제목 설명

그는 컬럼의 수를 알고있는 경우, 다음과 같은 세 가지 작업을 수행해야합니다

1. X 곱한 수의 각각의 섹션

2. X 다수의 각각의 섹션 플러스

3. 섹션의 수를 결정하고 각

입력 형식

첫 번째 라인은 각각 세 개의 정수 N, M, P를 함유하고, 총 수는 숫자, 동작의 열 수를 모듈로 (modulo).

수가 초기 값의 전 항목의 i 번째 열을 나타내고, 상기 제 2 라인은 공백으로 구분 N 정수를 포함한다.

다음 M 라인은 다음과 같은 3 또는 4의 정수, 동작을 나타내는 포함

동작 1 : 형식 : 1 명 XYK 의미 : Y (X), 상기 각 구간의 수를 곱한 값 k는

동작 2 : 형식 : 2 XYK 의미 구간 [X, Y 각각의 수 k는 플러스

작업 3 : 형식 : 3 XY 의미 : 출력 간격 [x 및 y,] 얻어진 결과를 모듈로 P의 각각의 숫자

출력 형식

출력은 라인의 정수, 세 작업의 결과가 포함되어 있습니다.

샘플 입출력

입력 # 1
38 5 5 
1 2 5 4 3 
2 1 4 1 
3 2 5 
1 2 4 2 
2 3 5 5 
3 1 4
출력 # 1
17 
2
#INCLUDE <. 비트 / stdc ++ H> 
의 typedef  LL;
사용하는  네임 스페이스 표준을;
CONST의  INT maxn 2E5 + = 9 ;
구조체 나무 {
     INT의 L, R; 
    LL의 합은, MUL을 추가; 
} A [maxn << 2 ]; 
LL S [maxn] P; 
보이드 업데이트 ( INT의 K) 
{ 
    A [K] .sum = (a [K << 1 ] .sum + A [K << 1 | 1 ] .sum) %의 P; 
} 
공극 빌드 ( INT의 K, INT의 L, INT의 R)
{ 
    A [K] 펜닐 = 1, A [K] = .R R; 
    A [K] .add = 0 ; 
    A [K] .mul = 1 ;
    경우 (L == R) 
    { 
        A [K] .sum = S [1]; 반환 ; 
    } 
    INT 중간 = (L + R) >> 1 ; 
    빌드 (K << 1 , L, MID); 
    빌드 (K << 1 | 1 중간 + 1 , R); 
    업데이트 (K); 
} 
공극 푸시 ( INT의 K) 
{ 
    경우 (== .L A [K] 이 [K]를 .R) 
    {
        A [K] .add = 0 ; 
        A [K] .mul = 1 ;
        반환 ; 
    } 
    INT 중간 = (a [K] 펜닐 + A [K] .R) >> 1 ; 
    A [K << 1 ] .sum = (a [K << 1 ] .sum * A [K] .mul + A [K] * .add (MID-A [K] 펜닐 + 1 )) %의 P; 
    A [K << 1 | 1 ] .sum = (a [K << 1 | 1 ] .sum * A [K] .mul + A [K] * .add (a [K] .R-MID)) %의 P; 
    A [K << 1 ] .add = (a [K << 1 ] .add * A [K] .mul + A [K] .add) %의 P; 
    A [K<< X)1 | 1 ] .add = (a [K << 1 | 1 ] .add * A [K] .mul + A [K] .add) %의 P; 
    A [K << 1 ] .mul = (a [K << 1 ] .mul * A [K] .mul) %의 P; 
    A [K << 1 | 1 ] .mul = (a [K << 1 | 1 ] .mul * A [K] .mul) %의 P; 
    A [K] .add = 0 ; 
    A [K] .mul = 1 ;
    반환 ; 
} 
공극 changeplus ( INT의 K, INT의 L, INT의 R, INT 
{ 
//을    COUT << A [K] .sum << "??"<< ENDL; 
    경우 (a [K] 펜닐> R || A [K] .R <l) ;
    경우 (L <= A [K] 펜닐 && R> = A [K] .R) 
    { 
        A [K] .sum = (a [K] + .sum X * (a [K] .ra [K] + .L 1 )) %의 P; 
        A [K] .add = (a [K] + .add X) %의 P;
        반환 ; 
    } 
    푸시 (K); 
    INT 중간 = (a [K] 펜닐 + A [K] .R) >> 1 ;
//     경우 (L <= MID) 
    changeplus (K << 1 , L, R, X);
//     (R> MID) 경우 
    changeplus (K << 1 | 1  ,
    ) 업데이트 (K
    
} 
공극 changemul ( INT의 K, INT의 L, INT의 R, INT의 X는) 
{ 
//     COUT << .sum << "!"<< ENDL [K]을; 
    경우 (a [K] 펜닐> R || A [K] .R <l) ;
    경우 (L <= A [K] 펜닐 && R> = A [K] .R) 
    { 
        A [K] .sum = (a [K] *의 .sum의 X) %의 P; 
        A [K] .mul = (a [K] .mul * X) %의 P; 
        A [K] .add = (a [K] * .add X) %의 P;
        반환 ; 
    } 
    푸시 (K); 
    INT 중간 = (a [K] 펜닐 + A [K] .R) >> 1 ;
//    경우 (L <= MID) 
    changemul (K << 1 , L, R, X);
//     (R> MID) 경우 
    changemul (K << 1 | 1 ], L, R, X) 
    업데이트 (K); 
    반환 ; 
} 
LL 쿼리 ( INT의 K, INT의 L, INT의 R) 
{ 
    경우 (R <A [K] 펜닐 || L>은 [K] .R) 복귀  0 ; 
    푸시 (K); 
    경우 (L <= A [K] 펜닐 && R> = A [K]를 .R) 
    { 
        반환 A [K] .sum 단계; 
    } 
    INT 중간 = (a [K] 펜닐 + A [K] .R) >> 1 ; 
    LL ANS = 0 ;
//     (L <= MID) 경우 
    ANS = (ANS 쿼리 + (K << 1 , L, R)) %의 P;
//     (R> MID) 경우 
    ANS = (ANS 쿼리 + (K << 1 | 1 %의, L, R)) ; P
    반환 ANS를; 
} 
INT 의 main () 
{ 
    INT의 N, m, I; 
    scanf와 ( " % D % % LLD D " , 및 N, M, P);
     (I = 1 ; i가 <= N; ++ i가 ) 
    는 scanf ( " %의 LLD " , S [I]); 
    구축 ( 1 , 1 , N);
    반면 M-- ( ) 
    { 
        INT, L, R을 선택; 
        게요 X; 
        scanf와 ( " %의 D " , 및 선택 해제);
        경우 (최적화 된 == 1 ) 
        { 
            는 scanf ( " % D % % LLD D ' , L, R, X); 
            changemul ( 1 , L, R, X); 
        } 
        경우 (최적화 된 == 2 ) 
        { 
            는 scanf ( " % D % % LLD D ' , L, R, X); 
            changeplus ( 1 , L, R, X); 
        } 
        경우 (최적화 된 == 3)  
        {
            는 scanf ( " % d 개 %의 D ' , L, R); 
            의 printf ( " % LLD \ 없음 " 쿼리 ( 1 , L, R)); 
        } 
    } 
}

 

추천

출처www.cnblogs.com/HHHEN/p/11724442.html