真就简单题
「我的做题历程」:
step1:观察题面。
「若
t
=
1
t = 1
t=1,则接下来有两个数
L
,
R
L,R
L,R,表示区间
[
L
,
R
]
[L, R]
[L,R] 的每个数均反转;若
t
=
2
t = 2
t=2 ,则接下来只有一个数
i
i
i,表示询问的下标。」 ,这……这不就是区间修改单点查询嘛。(靓仔无语中)
step2:思考解法。
第一种解法:起初,我想
0
/
1
0/1
0/1 反转应该是等价于奇偶性转换的,即偶数代表
0
0
0,奇数代表
1
1
1(譬如
2
2
2 是偶数,代表
0
0
0;
3
3
3 是奇数,代表
1
1
1)。因为奇数加奇数等于偶数,偶数加奇数等于奇数,所以可以得出任意一个数加上奇数,它的奇偶性就会发生变化(偶变奇,奇变偶)。刚好符合此处
0
/
1
0/1
0/1 反转的要求。于是,我们可以正常的做树状数组的区间修改单点查询,其增量为 1,单点查询时输出该数模
2
2
2 即为答案。(不知道树状数组的同学这边请 → 树状数组)
第二种解法:后来听评讲,发现了另一种高级做法——异或(异或,写作
⊕
\oplus
⊕,代码表示为 ^,意为将两个整数作为二进制数,对二进制表示中的每一位逐一运算,当且只当只有两个对应位不同时才为
1
1
1)。异或运算的逆运算是它本身,也就是说两次异或同一个数最后结果不变。而且异或符合交换律,即
a
⊕
b
⊕
c
=
a
⊕
c
⊕
b
a \oplus b \oplus c = a \oplus c \oplus b
a⊕b⊕c=a⊕c⊕b。我们可以利用异或的这些性质对树状数组进行处理,通过两次异或实现与区间修改,通过异或和实现单点查询。
step3:完成代码。
顺便说一下,虽然此题看似数据不大,但实际不写快读过不了(OJ 应该能过,柠檬上不行)。
// 解法一
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
int n, m, op, l, r, xi, BIT[N];
int lowbit(int x) { return x & -x; }
void update(int x, int k) {
for (int i = x; i <= n; i += lowbit(i)) {
BIT[i] += k;
}
return;
}
int sum(int x) {
int ans = 0;
for (int i = x; i >= 1; i -= lowbit(i)) {
ans += BIT[i];
}
return ans;
}
int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') {
f = -1;
}
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + ch - '0';
ch = getchar();
}
return x * f;
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++) {
scanf("%d", &op);
if (op == 1) {
l = read(), r = read();
update(l, 1);
update(r + 1, -1);
} else {
scanf("%d", &xi);
printf("%d\n", sum(xi) % 2); // 奇偶性代表 0/1
}
}
return 0;
}
// 解法二
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
int n, m, op, l, r, xi, BIT[N];
int lowbit(int x) { return x & -x; }
void update(int x, int k) {
for (int i = x; i <= n; i += lowbit(i)) {
BIT[i] ^= k;
}
return;
}
int sum(int x) {
int ans = 0;
for (int i = x; i >= 1; i -= lowbit(i)) {
ans ^= BIT[i];
}
return ans;
}
int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') {
f = -1;
}
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + ch - '0';
ch = getchar();
}
return x * f;
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++) {
scanf("%d", &op);
if (op == 1) {
l = read(), r = read();
update(l, 1);
update(r + 1, 1);
} else {
scanf("%d", &xi);
printf("%d\n", sum(xi));
}
}
return 0;
}
(简单的 Accepted ne……)
让我们来解决 『简单题』 叭~
Bye bye!!1 👋👋

2645

被折叠的 条评论
为什么被折叠?



