思路
如果说给你一个数组,有 \(q\) 组询问,询问一个区间的区间和,那么有最原始的做法。维护一个左端点和一个右端点,每次一位一位移动断点,那么时间复杂度是 \(n \times q\),那么如果我们将查询存起来,按一种我们想要的顺序去做呢?我们就可以排序,排序规则就是:
B = sqrt(n);
bool cmp(node _x, node _y) {
if (_x.l / B != _y.l / B) {
return _x.l / B < _y.l / B;
}
return _x.r < _y.r;
}
具体来说就是先将左端点分成一个一个的块,右端点则按从小到大排序即可。
时间复杂度
左端点在一个块内做多移动 \(n\) 次(|1,3,5,4,2|数字表示顺序),那么有 \(\sqrt{n}\) 的块,那就最多移动 \(n\times\sqrt{n}\)次
右端点也是一样
那么时间复杂度就是 \(O(2\timesn\times\sqrt{n})\)
code:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 5, B = 455;
struct node {
int l, r, id;
}a[N];
int n, q, x[N], ans[N];
bool cmp(node _x, node _y) {
if (_x.l / B != _y.l / B) {
return _x.l / B < _y.l / B;
}
return _x.r < _y.r;
}
signed main() {
cin >> n >> q;
for (int i = 1; i <= n; i++) {
cin >> x[i];
}
for (int i = 1; i <= q; i++) {
cin >> a[i].l >> a[i].r;
a[i].id = i;
}
sort(a + 1, a + q + 1, cmp);
for (int i = 1, lt = 1, rt = 1, tmp = x[1]; i <= q; i++) {
while (lt < a[i].l) {
tmp -= x[lt];
lt++;
}
while (rt < a[i].r) {
rt++;
tmp += x[rt];
}
while (lt > a[i].l) {
lt--;
tmp += x[lt];
}
while (rt > a[i].r) {
tmp -= x[rt];
rt--;
}
ans[a[i].id] = tmp;
}
for (int i = 1; i <= q; i++) {
cout << ans[i] << "\n";
}
return 0;
}
优势
如:做算区间内有多少种颜色时极其方便
劣势
如:时间复杂度很劣,远远没有线段树优秀
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5, B = 455;
struct node {
int l, r, id;
}a[N];
int n, q, x[N], ans[N], cnt = 0, mp[N + 5];
vector<int> v;
bool cmp(node _x, node _y) {
if (_x.l / B != _y.l / B) {
return _x.l / B < _y.l / B;
}
return _x.r < _y.r;
}
void check(int u, int op) {
if (op == 1) {
if (!mp[u]) {
cnt++;
}
mp[u]++;
}
else {
mp[u]--;
if (!mp[u]) {
cnt--;
}
}
}
int main() {
cin >> n >> q;
for (int i = 1; i <= n; i++) {
cin >> x[i];
v.push_back(x[i]);
}
sort(v.begin(), v.end());
for (int i = 1; i <= n; i++) {
x[i] = lower_bound(v.begin(), v.end(), x[i]) - v.begin();
}
for (int i = 1; i <= q; i++) {
cin >> a[i].l >> a[i].r;
a[i].id = i;
}
sort(a + 1, a + q + 1, cmp);
for (int i = 1, lt = 1, rt = 0; i <= q; i++) {
while (lt < a[i].l) {
check(x[lt], -1);
lt++;
}
while (rt < a[i].r) {
rt++;
check(x[rt], 1);
}
while (lt > a[i].l) {
lt--;
check(x[lt], 1);
}
while (rt > a[i].r) {
check(x[rt], -1);
rt--;
}
ans[a[i].id] = cnt;
}
for (int i = 1; i <= q; i++) {
cout << ans[i] << "\n";
}
return 0;
}
标签:rt,node,return,笛卡尔,int,--,lt
From: https://www.cnblogs.com/libohan/p/18427787