// 추가, 게으른 태그, 현재 노드를 루트로하는 각 서브 트리가 (루트 노드를 포함하지 않음)를 제공 플러스 추가 // 사용법 #include <cstdio> 사용법 #include <CString을> 사용법 #include <iostream> 사용법 #include < 알고리즘> 은 USING 스페이스 STD, 타입 정의 긴 롱 LL; CONST INT N = 100010 ; INT N-, m; INT W [N]을, 구조체 노드 { INT의 L을 R & LT; // 합 // 만 현재 노드와 자식 노드를 고려하면 마크는, 현재의 범위와 정도는 모든 조상의 마크를 고려하지 않은 노드 LL SUM은; // 게으른 마크 // 현재의 범위 플러스 추가의 모든 아들들에게 추가 LL; } TR [N * 4. ]; // 자식 노드의 부모 노드 정보에 대한 정보를 계산 보이드 의 팔 굽혀 펴기를 ( INT U) { TR [U] .sum = TR [U << . 1 ] + .sum TR [ << U 1. | 1. ] .sum; } 무효 푸시 ( INT U) { 노드 및 TR = 루트 [U], 좌측 = TR [U << 1이다. ], 오른쪽 = TR [U << 1. | 1이다. ]; // 현재의 루트가 표시되면, 아래로 통과뿐만 아니라 비어 IF (root.add) { left.add + = root.add; left.sum+ = (LL) (left.r - left.l + 1 ) * root.add; right.add + = root.add; right.sum + = (LL) (right.r - 알았네 + 1 ) * root.add; root.add = 0 ; } } 공극 빌드 ( INT U, INT (L), INT (R)) { 경우 (L == R) TR [U] [R] w = {L, R, 0 }; 또 { TR [U] = {L, R}; INT 중간 = L + R >> 1 ; 빌드 (U << 1 , L, MID); 빌드 (U << 1 | 1 중간 + 1 , R); (U)를 팔 굽혀 펴기; } } 공극 수정 ( INT U, INT (L), INT (R), INT의 D)을 { 경우 (TR [U] 펜닐> = 1 && TR [U] .R <= R) { // 总和 TR [U] .sum + = (LL) (TR [U] .R - TR [U] 펜닐 + 1 ) * D; // 懒标记 TR [U] .add + = D; } // 간격도 우리 분할해야 또 { 푸시 (U); INT 중간 TR = [U] 펜닐 + TR [U] .R >> 1 ; 경우 (L <= MID) 수정 (U << 1 , L, R, D); 경우 (R> MID) 수정 (U << 1 | 1 , L, R, D); // 当前区间和发生变化,需要向上传 팔 굽혀 펴기 (U); } } LL 쿼리 ( INT U, INT (L) 의 INT R) { 경우 (TR [U]는 .L> = 1 && TR [U] .R <=R) 복귀TR [U] .sum; // 查询子区间 푸시 (U); INT 중간 TR = [U] 펜닐 + TR [U] .R >> 1 ; LL 합 = 0 ; 경우 (L <= MID) 합계 = 쿼리 (U << 1 , L, R); 경우 (R> MID) 합계 + = 쿼리 (U << 1 | 1 , L, R); 반환 합; } INT 의 main () { 는 scanf ( " % D % D " , 및 N, m); 대 ( INT I =1 ; I <= N; I ++ ) 는 scanf ( " %의 D " , [I] w); 빌드 ( 1 , 1 , N); 숯 OP [ 2 ]; INT L, R, D; 반면 (m - ) { 는 scanf ( " % S % D % D " , OP, L, R); 경우 (* OP == ' C ' ) { 는 scanf ( " %의 D " , d); (수정 1 , L, R, D); } 사람 의 printf ( " %의 LLD \ n " 쿼리 ( 1 , L, R)); } 반환 0 ; }