0%

2569. 更新数组后处理求和查询

2569.更新数组后处理求和查询

题目描述:

两个下标从 $0$ 开始的数组 $num1,num2$ ,和一个二维数组 $queries$ 表示一些操作。

  • 操作类型 $1$ 为 $queries[i] = [1, l, r]$ 。你需要将 $nums1$ 从下标 $l$ 到下标 $r$ 的所有 $0$ 反转成 $1$ 或将 $1$ 反转成 $0$ 。 $l$ 和 $r$ 下标都从 $0$ 开始。
  • 操作类型 $2$ 为 $queries[i] = [2, p, 0]$ 。对于 $0 \le i < n$ 中的所有下标,令 $nums2[i] = nums2[i] + nums1[i] \times p$ 。
  • 操作类型 $3$ 为 $queries[i] = [3, 0, 0]$ 。求 $nums2$ 中所有元素的和。

数据范围:

$1\le len \le 10^5, 0\le nums1[i] \le 1, 0\le nums2[i]\le 10^9$

题解:

操作1将区间翻转, $1$ 的数量和 $0$ 的数量刚好翻转。操作2是在 $sum2$ 基础上加 $sum1 \times p$ ,也就是 $nums1$ 中 $1$ 的个数乘 $p$ 。操作3就是返回 $sum2$ 。

直接使用线段树维护 $nums1$ 区间中 $1$ 的个数,翻转时可以 $num1 = len - num0$ 。直接相减得到新的个数。注意维护bool型lazy标记时,下滤需要取反,标记都是取反。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
auto optimize_cpp_stdio = []()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();

class SegTree
{
public:
const static int maxn = 1e5 + 10;
struct Node
{
int l, r, val;
bool tag;
} tree[maxn << 2];
void build(int cur, int l, int r, vector<int> &nums)
{
tree[cur].l = l, tree[cur].r = r;
tree[cur].tag = false;
if (l == r)
{
tree[cur].val = nums[l];
return;
}
int mid = (l + r) >> 1;
build(cur << 1, l, mid, nums);
build(cur << 1 | 1, mid + 1, r, nums);
tree[cur].val = tree[cur << 1].val + tree[cur << 1 | 1].val;
}
void pushdown(int cur)
{
tree[cur << 1].val = (tree[cur << 1].r - tree[cur << 1].l + 1) - tree[cur << 1].val;
tree[cur << 1 | 1].val = (tree[cur << 1 | 1].r - tree[cur << 1 | 1].l + 1) - tree[cur << 1 | 1].val;
tree[cur << 1].tag = !tree[cur << 1].tag;
tree[cur << 1 | 1].tag = !tree[cur << 1 | 1].tag;
tree[cur].tag = 0;
}
void update(int cur, int l, int r)
{
if (l <= tree[cur].l && r >= tree[cur].r)
{
// 对 cur node 取反,维护1的个数
tree[cur].val = (tree[cur].r - tree[cur].l + 1) - tree[cur].val;
tree[cur].tag = !tree[cur].tag;
return;
}
int mid = (tree[cur].l + tree[cur].r) >> 1;
if (tree[cur].tag)
pushdown(cur);
if (l <= mid)
update(cur << 1, l, r);
if (mid + 1 <= r)
update(cur << 1 | 1, l, r);
tree[cur].val = tree[cur << 1].val + tree[cur << 1 | 1].val;
}
int query(int cur, int l, int r)
{
if (l <= tree[cur].l && tree[cur].r <= r)
return tree[cur].val;
int mid = (tree[cur].l + tree[cur].r) >> 1;
int sum = 0;
if (tree[cur].tag)
pushdown(cur);
// [l, mid]
if (l <= mid)
sum += query(cur << 1, l, r);
// [mid + 1, r]
if (mid + 1 <= r)
sum += query(cur << 1 | 1, l, r);
return sum;
}
} segTree;
class Solution
{
public:
const static int maxn = 1e5 + 10;
const static int maxm = 1e5 + 10;
const int INF = 0x3f3f3f3f;
vector<long long> handleQuery(vector<int> &nums1, vector<int> &nums2, vector<vector<int>> &queries)
{
int n1 = nums1.size(), n2 = nums2.size();
long long sum = 0;
for (int i = 0; i < n2; ++i)
sum += nums2[i];
SegTree segTree;
segTree.build(1, 0, n1 - 1, nums1);
vector<long long> ans;
for (auto &q : queries)
{
if (q[0] == 1)
segTree.update(1, q[1], q[2]);
else if (q[0] == 2)
sum += (long long)segTree.query(1, 0, n1 - 1) * (long long)q[1];
else
ans.emplace_back(sum);
}
return ans;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
namespace FAST_IO
{
static string buf_line;
static int _i;
static int _n;
static char _ch;
template <class T>
inline bool read(T &x)
{
T flag = 1;
x = 0;
if (_i >= _n)
return false;
_ch = buf_line[_i++];
while (_ch < '0' || _ch > '9')
{
if (_ch == '-')
flag = -1;
_ch = buf_line[_i++];
}
while (_ch >= '0' && _ch <= '9')
{
x = (x << 3) + (x << 1) + (_ch ^ 48), _ch = buf_line[_i++];
}
x *= flag;
return true;
}

template <class T, class... _T>
inline bool read(T &x, _T &...y)
{
return read(x), read(y...);
}

inline bool getline()
{
if (!getline(cin, buf_line))
return false;
_i = 0, _n = buf_line.length();
return true;
}
template <class T>
inline void show(T *a, int n)
{
cout << "[";
for (int i = 0; i < n; ++i)
{
if (i != 0)
cout << ",";
cout << a[i];
}
cout << "]";
}

bool endofl()
{
if (_i >= _n)
return true;
if (_i == 0)
return false;
if (buf_line[_i - 1] == ']')
{
_i++;
return true;
}
return false;
}

template <class T, std::size_t Num>
inline void show(T a[][Num], int n, int m)
{
cout << "[";
for (int i = 0; i < n; ++i)
{
if (i != 0)
cout << ",";
show(a[i], m);
}
cout << "]";
}
} // namespace FAST_IO
using namespace FAST_IO;

int init = []
{
/*********** fast_read ***************/
// freopen("in.txt", "r", stdin);
freopen("user.out", "w", stdout);
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
const static int maxn = 1e5 + 1;
class SegTree
{
public:
struct Node
{
int l, r, val;
bool tag;
} tree[maxn << 2];
void build(int cur, int l, int r, int *nums)
{
tree[cur].l = l, tree[cur].r = r;
tree[cur].tag = false;
if (l == r)
{
tree[cur].val = nums[l];
return;
}
int mid = (l + r) >> 1;
build(cur << 1, l, mid, nums);
build(cur << 1 | 1, mid + 1, r, nums);
tree[cur].val = tree[cur << 1].val + tree[cur << 1 | 1].val;
}
void pushdown(int cur)
{
tree[cur << 1].val = (tree[cur << 1].r - tree[cur << 1].l + 1) - tree[cur << 1].val;
tree[cur << 1 | 1].val = (tree[cur << 1 | 1].r - tree[cur << 1 | 1].l + 1) - tree[cur << 1 | 1].val;
tree[cur << 1].tag = !tree[cur << 1].tag;
tree[cur << 1 | 1].tag = !tree[cur << 1 | 1].tag;
tree[cur].tag = 0;
}
void update(int cur, int l, int r)
{
if (l <= tree[cur].l && r >= tree[cur].r)
{
// 对 cur node 取反,维护1的个数
tree[cur].val = (tree[cur].r - tree[cur].l + 1) - tree[cur].val;
tree[cur].tag = !tree[cur].tag;
return;
}
int mid = (tree[cur].l + tree[cur].r) >> 1;
if (tree[cur].tag)
pushdown(cur);
if (l <= mid)
update(cur << 1, l, r);
if (mid + 1 <= r)
update(cur << 1 | 1, l, r);
tree[cur].val = tree[cur << 1].val + tree[cur << 1 | 1].val;
}
int query(int cur, int l, int r)
{
if (l <= tree[cur].l && tree[cur].r <= r)
return tree[cur].val;
int mid = (tree[cur].l + tree[cur].r) >> 1;
int sum = 0;
if (tree[cur].tag)
pushdown(cur);
// [l, mid]
if (l <= mid)
sum += query(cur << 1, l, r);
// [mid + 1, r]
if (mid + 1 <= r)
sum += query(cur << 1 | 1, l, r);
return sum;
}
} segTree;
/*************************************/
int op, l, r, n1, n2, op_cnt, x;
int nums1[maxn], nums2[maxn];
long long sum;
while (true)
{
if (!getline())
break;
for (n1 = 0; read(x); n1++)
{
nums1[n1] = x;
}
getline();
for (n2 = 0, sum = 0; read(x); n2++)
{
nums2[n2] = x;
sum += x;
}
getline();
segTree.build(1, 0, n1 - 1, nums1);
cout << "[";
op_cnt = 0;
for (; !endofl();)
{
for (; !endofl();)
{
read(op, l, r);
if (op == 1)
segTree.update(1, l, r);
else if (op == 2)
sum += (long long)segTree.query(1, 0, n1 - 1) * l;
else
{
if (op_cnt++ > 0)
cout << ",";
cout << sum;
}
}
}
cout << "]\n";
}
exit(0);
return 0;
}();
class Solution {
public:
vector<long long> handleQuery(vector<int>& nums1, vector<int>& nums2, vector<vector<int>>& queries) {
return {};
}
};