dls的数据结构-分块,莫队
例题1
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
typedef long long LL;
const int M = 500;
LL tag[M + 5][M + 5];
LL val[N];
int main(){
int n, q; scanf("%d %d", &n, &q);
for(int i = 0; i < q; i ++){
int op; scanf("%d", &op);
if(op == 1){
int x, y, d; scanf("%d %d %d", &x, &y, &d);
if(x <= M){
tag[x][y] += d;
}
else{
for(int j = y; j <= n; j += x) val[j] += d;
}
}
else{
int x; scanf("%d", &x);
LL ans = val[x];
for(int j = 1; j <= M; j ++){
ans += tag[j][x % j];
}
printf("%lld\n", ans);
}
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
const int LOGN = 21;
int n, q;
long long val[N], f[22][N];
void init(){
// 这里注意val可能存在的边界问题
for(int i = 1; i <= n; i ++) f[0][i] = val[i];
for(int i = 1; i < LOGN; i ++){
for(int j = 1; j + (1 << (i - 1)) <= n; j ++){
f[i][j] = max(f[i - 1][j + (1 << (i - 1))], f[i - 1][j]);
}
}
}
unsigned int A, B, C;
inline unsigned int rng61() {
A ^= A << 16;
A ^= A >> 5;
A ^= A << 1;
unsigned int t = A;
A = B;
B = C;
C ^= t ^ A;
return C;
}
int main(){
scanf("%d%d%u%u%u", &n, &q, &A, &B, &C);
for(int i = 1; i <= n; i ++) val[i] = rng61();
init();
long long res = 0;
while(q --){
int l = rng61() % n + 1, r = rng61() % n + 1;
if(l > r) swap(l, r);
int len = __lg(r - l + 1);
res ^= max(f[len][l], f[len][r - (1 << len) + 1]);
}
cout << res << endl;
}
补充
a1 + a2 + a3 + a4 .... + ak = n, 最多有根号n个不同的数
莫队
加一个数,删一个数容易做容易实现
区间查询变成n*根号n次的加数和删数的操作
根据询问的区间,按照左端点所在的块进行分类
#include<bits/stdc++.h>
using namespace std;
const int N = 5e4+10;
typedef long long LL;
array<int, 3> que[N];
int cnt[N], c[N];
LL ans[N], res[N];
LL gcd(LL a, LL b){
return b ? gcd(b, a % b) : a;
}
int main(){
int n, m; scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i ++) scanf("%d", &c[i]);
for(int i = 1; i <= m; i ++){
int l, r; scanf("%d %d", &l, &r);
que[i] = {l, r, i};
res[i] = (LL)(r - l + 1) * (r - l) / 2;
}
const int M = 500;
sort(que + 1, que + n + 1, [&](array<int, 3> a, array<int, 3> b){
int id = a[0] / M;
if(id != b[0] / M) return id < b[0] / M;
else return id % 2 ? a[1] < b[1] : a[1] > b[1];
});
int tmp = 0;
auto add = [&](int x){
tmp += cnt[c[x]];
cnt[c[x]] ++;
};
auto del = [&](int x){
cnt[c[x]] --;
tmp -= cnt[c[x]];
};
int l = 1, r = 0;
for(int i = 1; i <= m; i ++){
while(r > que[i][1]) del(r), r --;
while(l < que[i][0]) del(l), l ++;
while(r < que[i][1]) r ++, add(r);
while(l > que[i][0]) l --, add(l);
ans[que[i][2]] = tmp;
}
for(int i = 1; i <= m; i ++){
LL d = gcd(ans[i], res[i]);
printf("%lld/%lld\n", ans[i] / d, res[i] / d);
}
}
include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
typedef long long LL;
array<int, 4> que[N];
int cnt[N], c[N], num[N];
int ans[N];
int main(){
int n; scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%d", &c[i]);
int m; scanf("%d", &m);
for(int i = 1; i <= m; i ++){
int l, r, k; scanf("%d %d %d", &l, &r, &k);
que[i] = {l, r, k, i};
}
const int M = 500;
sort(que + 1, que + m + 1, [&](array<int, 4> a, array<int, 4> b){
int id = a[0] / M;
if(id != b[0] / M) return id < b[0] / M;
else return id % 2 ? a[1] < b[1] : a[1] > b[1];
});
auto add = [&](int x){
num[cnt[c[x]]] --;
cnt[c[x]] ++;
num[cnt[c[x]]] ++;
};
auto del = [&](int x){
num[cnt[c[x]]] --;
cnt[c[x]] --;
num[cnt[c[x]]] ++;
};
int l = 1, r = 0;
for(int i = 1; i <= m; i ++){
while(r > que[i][1]) del(r), r --;
while(l < que[i][0]) del(l), l ++;
while(r < que[i][1]) r ++, add(r);
while(l > que[i][0]) l --, add(l);
ans[que[i][3]] = num[que[i][2]];
}
for(int i = 1; i <= m; i ++) printf("%d\n", ans[i]);
}