树状数组模板题 || [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 }

浙公网安备 33010602011771号