1+ import java .util .ArrayList ;
2+ import java .util .List ;
3+
4+ public class Solution6358 {
5+ public long [] handleQuery (int [] nums1 , int [] nums2 , int [][] queries ) {
6+ long sum2 = 0L ;
7+ for (int x : nums2 ) {
8+ sum2 += x ;
9+ }
10+
11+ SegmentTree segmentTree = new SegmentTree (nums1 );
12+ List <Long > resList = new ArrayList <>();
13+ for (int [] query : queries ) {
14+ if (query [0 ] == 1 ) {
15+ segmentTree .op1 (query [1 ] + 1 , query [2 ] + 1 );
16+ } else if (query [0 ] == 2 ) {
17+ sum2 += segmentTree .getSum () * query [1 ];
18+ } else {
19+ resList .add (sum2 );
20+ }
21+ }
22+ return resList .stream ().mapToLong (Long ::longValue ).toArray ();
23+ }
24+
25+ private static class SegmentTree {
26+ private final int N ;
27+ private final int [] nums ;
28+
29+ private final long [] sum ;
30+ private final int [] lazy ;
31+
32+ public SegmentTree (int [] nums ) {
33+ N = nums .length ;
34+ this .nums = nums ;
35+
36+ sum = new long [N * 4 ];
37+ lazy = new int [N * 4 ];
38+ build (1 , N , 1 );
39+ }
40+
41+ // 建树
42+ private void build (int s , int t , int p ) {
43+ if (s == t ) {
44+ sum [p ] = nums [s - 1 ];
45+ return ;
46+ }
47+ int mid = s + (t - s ) / 2 ;
48+ build (s , mid , p * 2 );
49+ build (mid + 1 , t , p * 2 + 1 );
50+ pushUp (p );
51+ }
52+
53+ // 将 nums1 从下标 l 到下标 r 的所有 0 反转成 1 或将 1 反转成 0 。
54+ public void op1 (int l , int r ) {
55+ this .op1 (l , r , 1 , N , 1 );
56+ }
57+
58+ // 区间 [l,r] 求和
59+ public long getSum () {
60+ return this .getSum (1 , N , 1 , N , 1 );
61+ }
62+
63+ private void op1 (int l , int r , int s , int t , int p ) {
64+ if (l <= s && t <= r ) {
65+ sum [p ] = (t - s + 1L ) - sum [p ];
66+ lazy [p ] ^= 1 ;
67+ return ;
68+ }
69+ int mid = s + (t - s ) / 2 ;
70+ pushDown (mid , s , t , p );
71+ if (l <= mid ) {
72+ op1 (l , r , s , mid , p * 2 );
73+ }
74+ if (r > mid ) {
75+ op1 (l , r , mid + 1 , t , p * 2 + 1 );
76+ }
77+ pushUp (p );
78+ }
79+
80+ private long getSum (int l , int r , int s , int t , int p ) {
81+ if (l <= s && t <= r ) {
82+ return sum [p ];
83+ }
84+ int mid = s + (t - s ) / 2 ;
85+ pushDown (mid , s , t , p );
86+ long sum = 0 ;
87+ if (l <= mid ) {
88+ sum = getSum (l , r , s , mid , p * 2 );
89+ }
90+ if (r > mid ) {
91+ sum += getSum (l , r , mid + 1 , t , p * 2 + 1 );
92+ }
93+ return sum ;
94+ }
95+
96+ private void pushDown (int mid , int s , int t , int p ) {
97+ if (lazy [p ] > 0 ) {
98+ sum [p * 2 ] = (mid - s + 1L ) - sum [p * 2 ];
99+ sum [p * 2 + 1 ] = (t - mid ) - sum [p * 2 + 1 ];
100+ lazy [p * 2 ] ^= lazy [p ];
101+ lazy [p * 2 + 1 ] ^= lazy [p ];
102+ lazy [p ] = 0 ;
103+ }
104+ }
105+
106+ private void pushUp (int p ) {
107+ sum [p ] = sum [p * 2 ] + sum [p * 2 + 1 ];
108+ }
109+ }
110+ }
111+ /*
112+ 6358. 更新数组后处理求和查询
113+ https://leetcode.cn/problems/handling-sum-queries-after-update/
114+
115+ 第 98 场双周赛 T4。
116+
117+ 给你两个下标从 0 开始的数组 nums1 和 nums2 ,和一个二维数组 queries 表示一些操作。总共有 3 种类型的操作:
118+ 1. 操作类型 1 为 queries[i] = [1, l, r] 。你需要将 nums1 从下标 l 到下标 r 的所有 0 反转成 1 或将 1 反转成 0 。l 和 r 下标都从 0 开始。
119+ 2. 操作类型 2 为 queries[i] = [2, p, 0] 。对于 0 <= i < n 中的所有下标,令 nums2[i] = nums2[i] + nums1[i] * p 。
120+ 3. 操作类型 3 为 queries[i] = [3, 0, 0] 。求 nums2 中所有元素的和。
121+ 请你返回一个数组,包含所有第三种操作类型的答案。
122+ 提示:
123+ 1 <= nums1.length,nums2.length <= 10^5
124+ nums1.length = nums2.length
125+ 1 <= queries.length <= 10^5
126+ queries[i].length = 3
127+ 0 <= l <= r <= nums1.length - 1
128+ 0 <= p <= 10^6
129+ 0 <= nums1[i] <= 1
130+ 0 <= nums2[i] <= 10^9
131+
132+ 线段树。基于 nums1 建树,懒标记下推 pushDown
133+ 时间复杂度 O(n + qlogn)
134+ 空间复杂度 O(4n)
135+ */
0 commit comments