Introduced
-
Classic problem: Given a sequence of support sections taken \ (\ min \) (given \ (l, r, x \ ) all satisfy \ (l \ le i \ le r \) a \ (a_i \) modified to \ (\ min (a_i, X) \) ) and a summation interval
-
Requires \ (O ((n + q ) \ log n) \) settled within a time
Algorithmic process
-
Ji driver segment tree is a tree line potential can be realized section taken \ (\ min / \ max \ ) segment sums
-
In \ (\ min \) as an example, each node maintains a line segment tree four values:
-
(1) \ (MX \) : maximum range
-
(2) \ (cnt \) : the number of occurrences maximum range
-
(3) \ (md \) (number strictly less than the maximum value and the maximum) time interval is greater:
-
(4) \ (SUM \) : intervals and
-
Take achieved interval \ (\ min \) , the line segment recursive tree consisting of nodes in the interrogation interval \ (P \) , the following process:
-
(1) If the \ (the X-\ GE mx_p \) , it is clear that this amendment does not affect the node \ (the p-\) , a direct return
-
(2) If the \ (the X-\ Le md_p \) , then to violence (p \) \ left and right child nodes recursively
-
(3) otherwise \ (md_p <the X-<mx_p \) , the modification of \ (sum_p \) can be calculated as \ (CNT_P \ Times (mx_p-the X-) \) , you can hit the mark
-
Consider illustrate the complexity of the algorithm.
-
Take note interval \ (\ min \) only the different numbers of the interval becoming identical
-
Easy to get a node to the tree line \ (p \) , last modified operation will only make up to node \ (p \) increase the number of different types of numbers within the interval represented by \ (1 \)
-
When the interval is recursively violence to modify operation of the node represents the number of different types bound to reduce the number of
-
That is, the number of all the nodes and increase the number of different types at most \ (O (q \ log n ) \) times, must also reduced by up \ (O ((n + q ) \ log n) \) times
-
Therefore, the total time complexity \ (O ((n + q ) \ log n) \)
Combined with the range of plus
-
Kyrgyzstan driver segment tree can also be added to the combination of range and just one more addition to marking
-
But it is worth noting: If there are sections plus the complexity of the operation to be more a \ (\ log \)
-
Analysis slightly
CF1290E Cartesian Tree
The meaning of problems
-
Given a \ (n-\) of arrangement \ (P \)
-
For each \ (. 1 \ I Le \ n-Le \) , the arrangement obtains all \ (\ le i \) a sequence (to maintain the relative positional relation) of the Cartesian tree (root large heap) the number of all the nodes constituting the size of the tree and child
-
\ (1 \ n \ the 150000 \)
practice
-
For a \ (n-\) sequence elements \ (A \) , which is a Cartesian node tree \ (I \) subtree size \ (. 1-nxt_i-pre_i \) ( \ (pre_i \) and \ (nxt_i \) are \ (a_i \) left and right of the first is greater than \ (a_i \) position, if it were not present \ (0 \) and \ (n-+. 1 \) )
-
So \ (i \) from small to large to maintain all \ (pre \) and \ (nxt \) and can be
-
But for ease of maintenance, we do not maintain a dynamic sequence, but at a length \ (n \) on the serial number of all small to large activation, and the \ (pre \) and \ (nxt \) redefined:
-
If \ (I \) first is bigger than its activated position to the left of the \ (J \) , then \ (pre_i \) is equal to \ (J \) and the total number of the right side is activated, if \ (J \) does not exist, \ (pre_i \) is added to the number of all active \ (1 \)
-
If \ (I \) is greater than a first right of its activated position \ (J \) , then \ (nxt_i \) is equal to \ (J \) and the total number of the left side is activated, if \ (J \) does not exist, \ (nxt_i \) is added to the number of all active \ (1 \)
-
This can be calculated if the former has joined \ (i \) a small number of the answer is \ (\ sum_j (pre_j + nxt_j ) -i ^ 2-2i \)
-
When the first \ (I \) views the first sequence \ (X \) digit is activated (i.e. \ (p_x = I \) ) when:
-
\ (pre_x = nxt_x = I +. 1 \) , can be processed directly
-
If \ (Y <X \) , then \ (nxt_y \) values shall \ (C \) take \ (\ min \) ( \ (C \) for the location \ (X \) left activated number number, including \ (X \) itself)
-
If \ (Y> X \) , then \ (nxt_y \) should be added \ (1 \)
-
That is, to achieve the interval to take \ (\ min \) and plus range, Kyrgyzstan driver segment tree maintenance can, \ (pre \) Similarly
-
\(O(n\log^2n)\)
Code
#include <bits/stdc++.h>
#define p2 p << 1
#define p3 p << 1 | 1
template <class T>
inline void read(T &res)
{
res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
if (bo) res = ~res + 1;
}
template <class T>
inline T Max(const T &a, const T &b) {return a > b ? a : b;}
template <class T>
inline T Min(const T &a, const T &b) {return a < b ? a : b;}
typedef long long ll;
const int N = 15e4 + 5, M = 6e5 + 5, INF = 0x3f3f3f3f;
int n, p[N], A[N];
void change(int x, int v)
{
for (; x <= n; x += x & -x)
A[x] += v;
}
int ask(int x)
{
int res = 0;
for (; x; x -= x & -x) res += A[x];
return res;
}
struct elem
{
int mx, cnt, md;
friend inline elem operator + (elem a, elem b)
{
elem res;
if (a.mx > b.mx) res = a, res.md = Max(a.md, b.mx);
else if (a.mx < b.mx) res = b, res.md = Max(a.mx, b.md);
else res = a, res.cnt = a.cnt + b.cnt, res.md = Max(a.md, b.md);
return res;
}
};
struct seg
{
elem T[M]; int add[M], tag[M], cnt[M]; ll sum[M];
void build(int l, int r, int p)
{
T[p] = (elem) {-INF, 0, -INF}; add[p] = 0; tag[p] = INF;
if (l == r) return;
int mid = l + r >> 1;
build(l, mid, p2); build(mid + 1, r, p3);
}
void down(int p)
{
T[p2].mx += add[p]; T[p2].md += add[p]; sum[p2] += 1ll * cnt[p2] * add[p];
add[p2] += add[p]; tag[p2] += add[p];
T[p3].mx += add[p]; T[p3].md += add[p]; sum[p3] += 1ll * cnt[p3] * add[p];
add[p3] += add[p]; tag[p3] += add[p];
if (tag[p] < T[p2].mx) sum[p2] -= 1ll * T[p2].cnt * (T[p2].mx - tag[p]),
tag[p2] = T[p2].mx = tag[p];
if (tag[p] < T[p3].mx) sum[p3] -= 1ll * T[p3].cnt * (T[p3].mx - tag[p]),
tag[p3] = T[p3].mx = tag[p];
add[p] = 0; tag[p] = INF;
}
void upt(int p)
{
cnt[p] = cnt[p2] + cnt[p3]; sum[p] = sum[p2] + sum[p3];
T[p] = T[p2] + T[p3];
}
void unlock(int l, int r, int pos, int v, int p)
{
if (l == r) return (void) (cnt[p] = T[p].cnt = 1, T[p].mx = sum[p] = v);
int mid = l + r >> 1; down(p);
if (pos <= mid) unlock(l, mid, pos, v, p2);
else unlock(mid + 1, r, pos, v, p3);
upt(p);
}
void change(int l, int r, int s, int e, int v, int p)
{
if (e < l || s > r) return;
if (s <= l && r <= e) return (void) (add[p] += v, tag[p] += v,
T[p].mx += v, T[p].md += v, sum[p] += 1ll * cnt[p] * v);
int mid = l + r >> 1; down(p);
change(l, mid, s, e, v, p2); change(mid + 1, r, s, e, v, p3);
upt(p);
}
void modify(int l, int r, int s, int e, int v, int p)
{
if (e < l || s > r) return;
if (s <= l && r <= e && v > T[p].md)
{
if (v < T[p].mx) sum[p] -= 1ll * T[p].cnt * (T[p].mx - v),
tag[p] = T[p].mx = v;
return;
}
int mid = l + r >> 1; down(p);
modify(l, mid, s, e, v, p2); modify(mid + 1, r, s, e, v, p3);
upt(p);
}
} T1, T2;
int main()
{
int x;
read(n);
for (int i = 1; i <= n; i++) read(x), p[x] = i;
T1.build(1, n, 1); T2.build(1, n, 1);
for (int i = 1; i <= n; i++)
{
change(p[i], 1); int c = ask(p[i]);
T1.modify(1, n, 1, p[i], c, 1); T1.change(1, n, p[i], n, 1, 1);
T2.modify(1, n, p[i], n, i - c + 1, 1); T2.change(1, n, 1, p[i], 1, 1);
T1.unlock(1, n, p[i], i + 1, 1); T2.unlock(1, n, p[i], i + 1, 1);
printf("%lld\n", T1.sum[1] + T2.sum[1] - 1ll * i * (i + 2));
}
return 0;
}
Section K small value
The meaning of problems
-
A length \ (n-\) sequence, all numbers are \ ([1, n] \ ) positive integer in the
-
\ (n-\) operations, each operation is a section taken \ (\ min \) or seek Interval \ (K \) a small value
-
\ (1 \ n, m \ 8 \ times10 ^ 4 \)
practice
-
Easy to think of the position of the line segment tree tree cover weight
-
When the query is split into the interrogation zone \ (O (\ log n) \) outer layers carry out nodes, these nodes embedded binary tree to segment
-
For the modification, the outer layer of the tree line is marked to take \ (\ min \) marks, but here there is a problem: For flagged by the node, its ancestor nodes embedded segment tree can not be achieved quickly modified.
-
So consider the tree line and Kyrgyzstan drivers thought the same: the same number of modifications put together.
-
When modifications to the split in the outer segment tree all \ (O (\ log n) \) nodes, the nodes find out all the different nature is greater than \ (X \) is the number of nodes and their ancestors in this these number changed to \ (x \) to
-
The number of each note within this number of nodes of different nature Save \ (1 \) , to be in the \ (O (\ log n) \) trees, the trees do modify the inner segment, which is required \ (O ( \ log ^ 2n) \) complexity
-
Therefore, the total complexity of the \ (O ((n + q ) \ log ^ 3n) \)
Code
#include <bits/stdc++.h>
#define p2 p << 1
#define p3 p << 1 | 1
template <class T>
inline void read(T &res)
{
res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
if (bo) res = ~res + 1;
}
template <class T>
inline T Min(const T &a, const T &b) {return a < b ? a : b;}
const int N = 8e4 + 5, M = N << 2, L = 3e7 + 5;
int n, m, a[N], rt[M], tag[M], ToT, tot, pt[N], nc, del[L], qaq, pos[N], val[N];
struct seg
{
int lc, rc, sum;
} T[L];
inline int newnode() {return nc ? del[nc--] : ++ToT;}
inline void delnode(int p) {T[p].lc = T[p].rc = T[p].sum = 0; del[++nc] = p;}
void change(int l, int r, int pos, int v, int &p)
{
if (!v) return;
if (!p) p = newnode(); T[p].sum += v;
if (l == r) return;
int mid = l + r >> 1;
if (pos <= mid) change(l, mid, pos, v, T[p].lc);
else change(mid + 1, r, pos, v, T[p].rc);
}
void dfs(int p)
{
if (!p) return;
dfs(T[p].lc); dfs(T[p].rc);
delnode(p);
}
int ask(int l, int r, int x, int p)
{
if (l == r) return 0;
int mid = l + r >> 1, res;
if (x <= mid) res = ask(l, mid, x, T[p].lc) + T[T[p].rc].sum,
dfs(T[p].rc), T[p].rc = 0;
else res = ask(mid + 1, r, x, T[p].rc);
return T[p].sum = T[T[p].lc].sum + T[T[p].rc].sum, res;
}
void zzq(int x, int &p) {change(1, n, x, ask(1, n, x, p), p);}
void build(int l, int r, int p)
{
tag[p] = n;
for (int i = l; i <= r; i++) change(1, n, a[i], 1, rt[p]);
if (l == r) return;
int mid = l + r >> 1;
build(l, mid, p2); build(mid + 1, r, p3);
}
void down(int p)
{
tag[p2] = Min(tag[p2], tag[p]);
tag[p3] = Min(tag[p3], tag[p]);
zzq(tag[p], rt[p2]); zzq(tag[p], rt[p3]);
tag[p] = n;
}
void zhouzhouzka(int l, int r, int x, int p)
{
if (x > r || !T[p].sum) return;
if (l == r) return (void) (pos[++qaq] = l, val[qaq] = T[p].sum);
int mid = l + r >> 1;
zhouzhouzka(l, mid, x, T[p].lc);
zhouzhouzka(mid + 1, r, x, T[p].rc);
}
void getmin(int l, int r, int s, int e, int x, int p)
{
if (e < l || s > r) return;
if (s <= l && r <= e)
{
tag[p] = Min(tag[p], x); qaq = 0; zhouzhouzka(1, n, x + 1, rt[p]);
zzq(x, rt[p]);
for (int i = 1; i <= qaq; i++)
for (int q = p >> 1; q; q >>= 1)
change(1, n, pos[i], -val[i], rt[q]),
change(1, n, x, val[i], rt[q]);
return;
}
int mid = l + r >> 1; down(p);
getmin(l, mid, s, e, x, p2); getmin(mid + 1, r, s, e, x, p3);
}
void czx(int l, int r, int s, int e, int x, int p)
{
if (e < l || s > r) return;
if (s <= l && r <= e) return (void) (pt[++tot] = rt[p]);
int mid = l + r >> 1; down(p);
czx(l, mid, s, e, x, p2); czx(mid + 1, r, s, e, x, p3);
}
int query(int l, int r, int k)
{
tot = 0; czx(1, n, l, r, n, 1);
int d = 0;
for (int i = 1; i <= tot; i++) d += T[pt[i]].sum;
l = 1; r = n;
while (l < r)
{
int delta = 0, mid = l + r >> 1;
for (int i = 1; i <= tot; i++) delta += T[T[pt[i]].lc].sum;
if (k <= delta)
{
r = mid;
for (int i = 1; i <= tot; i++) pt[i] = T[pt[i]].lc;
}
else
{
k -= delta; l = mid + 1;
for (int i = 1; i <= tot; i++) pt[i] = T[pt[i]].rc;
}
}
return l;
}
int main()
{
int op, l, r, x;
read(n); read(m);
for (int i = 1; i <= n; i++) read(a[i]);
build(1, n, 1);
while (m--)
{
read(op); read(l); read(r); read(x);
if (op == 1 && x > n) x = n;
if (op == 1) getmin(1, n, l, r, x, 1);
else printf("%d\n", query(l, r, x));
}
return 0;
}