树状数组介绍
是什么
一种统计数据的方式(结构为数组)
用处
大数据的 点增 & 前缀和
上手实操
基本代码
1 2 3 4
| const int N; int n; ll tr[N];
|
1 2 3 4 5 6 7 8 9 10 11 12
| inline int lowbit(int x){return x & -x;}
|
1 2 3 4 5 6
| void add(int x,int k){ for(int i=1;i<=x;i+=lowbit(i)){ tr[i]+=k; } }
|
1 2 3 4 5 6 7 8
| ll sum(int x){ ll s=0; for(int i=x;i>0;i-=lowbit(i)){ s+=tr[i]; } return s; }
|
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
| const int N; int n; ll tr[N];
inline int lowbit(int x){return x & -x;}
void add(int x,int k){ for(int i=1;i<=x;i+=lowbit(i)){ tr[i]+=k; } }
ll sum(int x){ ll s=0; for(int i=x;i>0;i-=lowbit(i)){ s+=tr[i]; } return s; }
|
模板题
P3374 树状数组 1
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
| #include <bits/stdc++.h> using namespace std; #define ll long long
const int N = 5e5 + 5; int n, m; int a[N]; ll tr[N];
inline int lowbit(int x){return x & -x;}
void add(int x, int k) { for (int i = x;i <= n;i += lowbit(i))tr[i] += k; }
ll sum(int x) { ll res = 0; for (int i = x;i > 0;i -= lowbit(i)) { res += tr[i]; } return res; }
int main() { cin >> n >> m; for (int i = 1;i <= n;i++) { cin >> a[i]; add(i, a[i]); }
for (int i = 1;i <= m;i++) { int q, x, y; cin >> q >> x >> y; if (q == 1) { add(x, y); } else { cout << sum(y) - sum(x - 1) << endl; } } return 0; }
|
很简单 (毕竟是模板题) ,把上面的基本代码背下来就行了(点增,前缀和,lowbit)。
接下来,你可以试试 这道题 (模板 2) 和 这道题 (逆序对)
逆序对答案:
只有不爱动脑的人才会打开我 QvQ
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
| #include <bits/stdc++.h> using namespace std; #define ll long long
const int N = 5e5 + 5; int n; int a[N], b[N]; int tr[N];
inline int lowbit(int x) { return x & -x; }
void add(int x, int k, int m) { for (int i = x;i <= m;i += lowbit(i))tr[i] += k; }
ll sum(int x) { ll res = 0; for (int i = x;i > 0;i -= lowbit(i)) { res += tr[i]; } return res; }
int main() { cin >> n; for (int i = 1;i <= n;i++) { cin >> a[i]; b[i] = a[i]; } sort(b + 1, b + n + 1); int m = unique(b + 1, b + n + 1) - (b + 1); for (int i = 1;i <= n;i++) { a[i] = lower_bound(b + 1, b + m + 1, a[i]) - b; } ll ans = 0; for (int i = 1;i <= n;i++) { ans += (i - 1) - sum(a[i]); add(a[i], 1, m); } cout << ans; return 0; }
|
然后再去看 P4378 (这道题其实模拟就能过,用树状数组还不知道要多麻烦。就当放松心情了)
答案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include <bits/stdc++.h> using namespace std;
int main() { int n; cin >> n; vector<pair<int, int>> v(n); for (int i = 0;i < n;i++) { int x; cin >> x; v[i] = { x,i }; } sort(v.begin(), v.end());
int maxx = 0; for (int i = 0;i < n;i++) { maxx = max(maxx, v[i].second - i); } cout << maxx + 1 << '\n'; }
|
尾
希望本篇文章对你有帮助 QWQ ,有任何问题都可以在评论区提出哦~