zkw Segment Tree Template summary
Initialize
int N = 4;
while (N-2 < n) n <<= 1;
Achievements
void Build () {for
(int i = n+n+1>>1; i; i--) pushup (i);
}
single point change, Interval summation
void Modify (int x, Long long Val) {for
(tr[x + = N] = val; x >>= 1;) pushup (x);
}
Long long query (int l, int r) {
int ans = 0;
For (l+=n-1, r+=n+1; l^r^1; l>>=1, r>>=1) {
if (~l&1) ans + = tr[l^1];
if (r&1) ans + = tr[r^1];
}
return ans;
}
interval Plus, single point check
void Modify (int l, int R, Long long Val) {for
(l+=n-1, r+=n+1; l^r^1; l>>=1, r>>=1) {
if (~l&1) t R[l^1] + = val;
if (r&1) tr[r^1] + = val;
}
}
Long long query (int x) {
long long ans = 0;
for (x + = N; x; x >>= 1) ans + = tr[x];
return ans;
}
interval Plus, interval check min
inline void pushup (int x) {
Register int tmp = Std::min (tr[x<<1], tr[x<<1|1]);
TR[X<<1]-= tmp; TR[X<<1|1]-= tmp; TR[X] + = tmp
;
void Modify (int l, int r, int val) {for
(l+=n-1, r+=n+1; l^r^1; pushup (l>>=1), Pushup (r>>=1)) {
if (~ l&1) tr[l^1] + = val;
if (r&1) tr[r^1] + = val
;
while ((l>>=1) ^ (r>>=1)) Pushup (L), Pushup (r);
Do Pushup (l); while (l >>= 1); notice!
}
int query (int l, int r) {
int ans = INF;
For (l+=n-1, r+=n+1; l^r^1; pushup (l>>=1), Pushup (r>>=1)) {
if (~l&1) Min (ans, tr[l^1]);
if (r&1) Min (ans, tr[r^1]);
}
return ans;
}
interval Plus, interval check
Long Long f[2050000], g[2050000]; int lv[2050000];
LV[X] = lv[x<<1] + 1; inline void pushup (int x) {f[x] = f[x<<1] + f[x<<1|1] + (G[x] << lv[x]), void modify (int l, int r , Long long Val) {for (l+=n-1, r+=n+1; l^r^1; pushup (l>>=1), Pushup (r>>=1)) {if (~l&1) g[l^1
] + = val, f[l^1] + = val << lv[l];
if (r&1) g[r^1] + = val, f[r^1] + = val << lv[r];
} while ((l>>=1) ^ (r>>=1)) Pushup (L), Pushup (R); Do Pushup (l);
while (l >>= 1);
A long long query (int l, int r) {Long long ans = 0, dl = 0, Dr = 0;
For (l+=n-1, r+=n+1; l^r^1; l>>=1, r>>=1) {ans + = dl * G[l] + dr * G[r];
if (~l&1) ans + = f[l^1], dl + = 1 << lv[l];
if (r&1) ans + = f[r^1], Dr + = 1 << lv[r];
} do ans + = dl * G[l] + dr * G[r];
while ((l>>=1) ^ (r>>=1));
DL + = Dr; Do ans + = dl * G[l];
while (l >>= 1); }
Note: the maintenance interval plus interval Check 3 methods, from the code length, time constants, spatial constants three aspects, there are tree arrays < zkw segment Tree < segment tree
Tree-shaped array version:
Long Long P[MAXN], Q[MAXN];
inline void Add (long long *tr, int x, long long v) {do
tr[x] + = V, while ((x + = x&-x) <= n);
}
inline long long sum (long long *tr, int x) {
long long ans = 0;
Do ans + = tr[x]; while (x-= x&-x);
return ans;
}
#define PUT (x,v) Add (p,x,v), add (q,x,v*x)
#define GET (x) (SUM (p,x) * (x+1)-sum (q,x))
inline void Modify (int l, int R, Long long Val) {put (l,val); put (r,-val);}
Inline long long query (int l, int r) {return get (R)-Get (L-1);}
zkw segment tree on two points
Maximum value of TR in the ratio of size
int suc (int x, int val) { //after X is the position of the first >= Val (excluding X)
while ((x&1) | | tr[x^1] < val) x >>= 1;
x ^= 1;
while (x < N) x |= tr[x <<= 1] < Val;
return x;
}
int pre (int x, int val) { //for x before the position of the first >= Val (excluding X)
while ((~x&1) | | tr[x^1] < val) x >>= 1;
x ^= 1;
while (x < N) x |= tr[(x <<= 1) | |] >= val;
return x;
}
The total number of TR stored in a few numbers
int suc (int x, int k) { //for x backward number k (excluding X) while
((x&1) | | (K-= tr[x^1]) > 0) x >>= 1;
K + = Tr[x ^= 1];//at this time k into the X subtree within the left starting from 1 number while
(x < N)
if (k > tr[x <<= 1])
K-= tr[x], x |= 1;
return x;
}
int pre (int x, int k) { //x forward number k (excluding X) while
((~x&1) | | (K-= tr[x^1]) > 0) x >>= 1;
K =-K; x ^= 1; At this point K becomes the X subtree within the left starting from 0 number
while (x < N)
if (k >= tr[x <<= 1])
K-= tr[x], x |= 1;
return x;
}
Note: In this regard, the function of the tree array is strictly lower than the ZKW segment tree
Two points on a tree array can only be one side, because essentially, only the value of Zuozi is preserved. You cannot ask both sides at the same time . Ask for the first from the beginning, can count the number, but also can be compared to the size of the X forward number, can only calculate the number of
Also note that the tree array cannot be stored to n and should be stored to n
int first (int val) {//head a >= val position int x = 0, i = N;
while (I >>= 1)//for (int i = n>>1; i; I >>= 1) if (Tr[x|i] < val) x |= i; return x + 1; notice!
Because the index of the tree array is organized, the movement of x is always lagging} int rank (int k) {//start from scratch k int x = 0, i = N;
while (I >>= 1) if (K > Tr[x|i]) k-= Tr[x |= i];
return x + 1;
} int pre (int x, int k) {//X forward number of K (including X) while ((K-= tr[x]) > 0) x-= x&-x;
K =-K; int i = x&-x;
X-= i;
while (I >>= 1) if (k >= tr[x|i]) K-= Tr[x |= i]; }