This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub ei1333/library
#include "structure/others/sqrt-decomposition.hpp"
template< typename T, typename E = int > struct SqrtDecomposition { vector< E > block_add, elem_add; vector< int > block_pos; vector< T > data, lsum; vector< vector< T > > sum; int N, B, K; E L; SqrtDecomposition(int N, E L = 0) : N(N), L(L) { // find the sum of L or more in the interval B = (int) sqrt(N); K = (N + B - 1) / B; block_add.assign(K, 0); block_pos.resize(N); for(int k = 0; k < K; k++) { for(int i = k * B; i < min((k + 1) * B, N); i++) block_pos[i] = k; } elem_add.assign(N, 0); data.assign(N, 0); sum.assign(K, vector< T >(B, 0)); lsum.assign(K, 0); } void build(const vector< E > &add, const vector< T > &dat) { assert(add.size() == elem_add.size()); assert(dat.size() == data.size()); elem_add = add; data = dat; for(int k = 0; k < K; k++) { E tap = elem_add[k * B]; for(int i = k * B; i < min((k + 1) * B, N); i++) tap = min(tap, elem_add[i]); block_add[k] = tap; for(int i = k * B; i < min((k + 1) * B, N); i++) { elem_add[i] -= block_add[k]; set(i, dat[i]); } } } inline void del(int k) { sum[block_pos[k]][elem_add[k]] -= data[k]; if(block_add[block_pos[k]] + elem_add[k] >= L) lsum[block_pos[k]] -= data[k]; } inline void set(int k) { while(sum[block_pos[k]].size() <= elem_add[k]) sum[block_pos[k]].push_back(0); sum[block_pos[k]][elem_add[k]] += data[k]; if(block_add[block_pos[k]] + elem_add[k] >= L) lsum[block_pos[k]] += data[k]; } void set(int k, T x) { data[k] = x; set(k); } void add(int a, int b) { for(int k = 0; k < K; k++) { int l = k * B; int r = min(l + B, N); if(r <= a || b <= l) { } else if(a <= l && r <= b) { block_add[k]++; if(0 <= L - block_add[k] && L - block_add[k] < sum[k].size()) { lsum[k] += sum[k][L - block_add[k]]; } } else { for(int i = max(a, l); i < min(b, r); i++) { del(i); elem_add[i]++; set(i); } } } } void sub(int a, int b) { for(int k = 0; k < K; k++) { int l = k * B; int r = min(l + B, N); if(r <= a || b <= l) { } else if(a <= l && r <= b) { if(0 <= L - block_add[k] && L - block_add[k] < sum[k].size()) { lsum[k] -= sum[k][L - block_add[k]]; } block_add[k]--; } else { if(0 <= L - block_add[k] && L - block_add[k] < sum[k].size()) { lsum[k] -= sum[k][L - block_add[k]]; } block_add[k]--; for(int i = l; i < max(a, l); i++) { del(i); elem_add[i]++; set(i); } for(int i = min(b, r); i < r; i++) { del(i); elem_add[i]++; set(i); } } } } T query(int a, int b, E x) { T ret = 0; for(int k = 0; k < K; k++) { int l = k * B; int r = min(l + B, N); if(r <= a || b <= l) { } else if(a <= l && r <= b) { if(0 <= x - block_add[k] && x - block_add[k] < sum[k].size()) { ret += sum[k][x - block_add[k]]; } } else { for(int i = max(a, l); i < min(b, r); i++) { if(block_add[k] + elem_add[i] == x) ret += data[i]; } } } return ret; } T query_low(int a, int b) { T ret = 0; for(int k = 0; k < K; k++) { int l = k * B; int r = min(l + B, N); if(r <= a || b <= l) { } else if(a <= l && r <= b) { ret += lsum[k]; } else { for(int i = max(a, l); i < min(b, r); i++) { if(block_add[k] + elem_add[i] >= L) ret += data[i]; } } } return ret; } };
#line 1 "structure/others/sqrt-decomposition.hpp" template< typename T, typename E = int > struct SqrtDecomposition { vector< E > block_add, elem_add; vector< int > block_pos; vector< T > data, lsum; vector< vector< T > > sum; int N, B, K; E L; SqrtDecomposition(int N, E L = 0) : N(N), L(L) { // find the sum of L or more in the interval B = (int) sqrt(N); K = (N + B - 1) / B; block_add.assign(K, 0); block_pos.resize(N); for(int k = 0; k < K; k++) { for(int i = k * B; i < min((k + 1) * B, N); i++) block_pos[i] = k; } elem_add.assign(N, 0); data.assign(N, 0); sum.assign(K, vector< T >(B, 0)); lsum.assign(K, 0); } void build(const vector< E > &add, const vector< T > &dat) { assert(add.size() == elem_add.size()); assert(dat.size() == data.size()); elem_add = add; data = dat; for(int k = 0; k < K; k++) { E tap = elem_add[k * B]; for(int i = k * B; i < min((k + 1) * B, N); i++) tap = min(tap, elem_add[i]); block_add[k] = tap; for(int i = k * B; i < min((k + 1) * B, N); i++) { elem_add[i] -= block_add[k]; set(i, dat[i]); } } } inline void del(int k) { sum[block_pos[k]][elem_add[k]] -= data[k]; if(block_add[block_pos[k]] + elem_add[k] >= L) lsum[block_pos[k]] -= data[k]; } inline void set(int k) { while(sum[block_pos[k]].size() <= elem_add[k]) sum[block_pos[k]].push_back(0); sum[block_pos[k]][elem_add[k]] += data[k]; if(block_add[block_pos[k]] + elem_add[k] >= L) lsum[block_pos[k]] += data[k]; } void set(int k, T x) { data[k] = x; set(k); } void add(int a, int b) { for(int k = 0; k < K; k++) { int l = k * B; int r = min(l + B, N); if(r <= a || b <= l) { } else if(a <= l && r <= b) { block_add[k]++; if(0 <= L - block_add[k] && L - block_add[k] < sum[k].size()) { lsum[k] += sum[k][L - block_add[k]]; } } else { for(int i = max(a, l); i < min(b, r); i++) { del(i); elem_add[i]++; set(i); } } } } void sub(int a, int b) { for(int k = 0; k < K; k++) { int l = k * B; int r = min(l + B, N); if(r <= a || b <= l) { } else if(a <= l && r <= b) { if(0 <= L - block_add[k] && L - block_add[k] < sum[k].size()) { lsum[k] -= sum[k][L - block_add[k]]; } block_add[k]--; } else { if(0 <= L - block_add[k] && L - block_add[k] < sum[k].size()) { lsum[k] -= sum[k][L - block_add[k]]; } block_add[k]--; for(int i = l; i < max(a, l); i++) { del(i); elem_add[i]++; set(i); } for(int i = min(b, r); i < r; i++) { del(i); elem_add[i]++; set(i); } } } } T query(int a, int b, E x) { T ret = 0; for(int k = 0; k < K; k++) { int l = k * B; int r = min(l + B, N); if(r <= a || b <= l) { } else if(a <= l && r <= b) { if(0 <= x - block_add[k] && x - block_add[k] < sum[k].size()) { ret += sum[k][x - block_add[k]]; } } else { for(int i = max(a, l); i < min(b, r); i++) { if(block_add[k] + elem_add[i] == x) ret += data[i]; } } } return ret; } T query_low(int a, int b) { T ret = 0; for(int k = 0; k < K; k++) { int l = k * B; int r = min(l + B, N); if(r <= a || b <= l) { } else if(a <= l && r <= b) { ret += lsum[k]; } else { for(int i = max(a, l); i < min(b, r); i++) { if(block_add[k] + elem_add[i] >= L) ret += data[i]; } } } return ret; } };