Loading

树状数组模板题 || [CQOI2006]简单题

题目描述

有一个 n 个元素的数组,每个元素初始均为 0。有 m 条指令,要么让其中一段连续序列数字反转——0 变 1,1 变 0(操作 1),要么询问某个元素的值(操作 2)。 例如当 n = 20 时,10 条指令如下:

输入格式

第一行包含两个整数 n, m,表示数组的长度和指令的条数; 以下 m 行,每行的第一个数 t 表示操作的种类:

若 t = 1,则接下来有两个数 L, R,表示区间 [L, R] 的每个数均反转; 若 t = 2,则接下来只有一个数 i,表示询问的下标。

输出格式

每个操作 2 输出一行(非 0 即 1),表示每次操作 2 的回答。

输入输出样例

输入 #1
20 10
1 1 10
2 6
2 12
1 5 12
2 6
2 15
1 6 16
1 11 17
2 12
2 6
输出 #1
1
0
0
0
1
1

说明/提示

对于 50% 的数据,1 ≤ n ≤ 103103, 1 ≤ m ≤ 104104; 对于 100% 的数据,1 ≤ n ≤ 105105, 1 ≤ m ≤ 5 × 105105,保证 L ≤ R。

首先是树状数组的一个模板题,作为树状数组可以干两件事(一个是对原数组操作另一个转变为差分数组操作,这里就不多赘述了),首先那想到了差分做法,但是我没搞清楚XOR操作该如何实现,可能要改内部实现原理? 很明显是不可取的,于是看了评论区一个非常妙的做法 :对于一个区间加上1不就改变奇偶性了么,奇偶性又可以映射到01...

代码 : 

 1 #include <bits/stdc++.h>
 2 #define gogo ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
 3 using namespace std;
 4 //using i64 = long long;
 5 const string YES = "Yes";
 6 const string NO = "No";
 7 template <typename T>
 8 class BIT {
 9     public:
10     vector<T> c;
11     int n;
12     BIT(int _n) : n(_n) {
13         c.resize(n);
14     }
15     void modify(int x, T v) {
16     while (x < n) {
17         c[x] += v;
18         x |= (x + 1);
19         }
20     }
21     T query(int x) {
22         T v{};
23         while (x >= 0) {
24             v += c[x];
25             x = (x & (x + 1)) - 1;
26         }
27         return v;
28     }
29     T get(int l, int r) {
30         return query(r) - query(l - 1);
31     }
32 };
33 
34 int32_t main() { 
35     gogo;
36     int n, m;
37     cin >> n >> m;
38     BIT<int64_t> c(n + 1);
39     for (int i = 1;i <= m;i ++) {
40         int o;
41         cin >> o;
42         if (o == 1) {
43             int l, r;
44             cin >> l >> r;
45             c.modify(l, 1), c.modify(r + 1, -1);
46         } else {
47             int x;
48             cin >> x;
49             cout << c.query(x) % 2 << endl;
50         }
51     }
52 }   

 

posted @ 2023-02-09 21:29  KakaDBL  阅读(47)  评论(0)    收藏  举报