Initial Sequence 1, 2,..., n, m operations (1 <= n, m <= 50000), each operation can be:
D l r: Copy all numbers in the range [L, R] once;
Q l r: Maximum number of the same number in the output range [L, R.
(0 <= R-l <= 10 ^ 8, 1 <= L, r <= number of sequence elements)
Question link: http://acm.hdu.edu.cn/showproblem.php? PID = 1, 4973
--> Because the numbers in the interval increase sequentially, you can use numbers as the leaf-built line segment tree to maintain the maximum number of the same number in the interval ..
The original query interval [L, R] is converted into a line segment tree query of the range [L-digit-corresponding number, R-digit-corresponding number ..
The next step is the line segment tree operation of sb ..
Note the interval segment processing ..
#include <cstdio>#include <algorithm>#define lc (o << 1)#define rc ((o << 1) | 1)using std::max;const int MAXN = 50000 + 10;int mul[MAXN << 2];long long sum[MAXN << 2], maxv[MAXN << 2];int ReadInt(){ int ret = 0; char ch; while ((ch = getchar()) && ch >= '0' && ch <= '9') { ret = ret * 10 + ch - '0'; } return ret;}void Pushdown(int o){ if (mul[o]) { mul[lc] += mul[o]; mul[rc] += mul[o]; sum[lc] <<= mul[o]; sum[rc] <<= mul[o]; maxv[lc] <<= mul[o]; maxv[rc] <<= mul[o]; mul[o] = 0; }}void Maintain(int o){ sum[o] = sum[lc] + sum[rc]; maxv[o] = max(maxv[lc], maxv[rc]);}void Build(int o, int L, int R){ mul[o] = 0; if (L == R) { sum[o] = 1; maxv[o] = 1; return; } int M = (L + R) >> 1; Build(lc, L, M); Build(rc, M + 1, R); Maintain(o);}int QueryFigure(int o, int L, int R, long long index){ if (L == R) return L; Pushdown(o); int M = (L + R) >> 1; return index <= sum[lc] ? QueryFigure(lc, L, M, index) : QueryFigure(rc, M + 1, R, index - sum[lc]);}long long QuerySum(int o, int L, int R, int ql, int qr){ if (ql <= L && R <= qr) return sum[o]; Pushdown(o); int M = (L + R) >> 1; long long ret = 0; if (ql <= M) { ret += QuerySum(lc, L, M, ql, qr); } if (qr > M) { ret += QuerySum(rc, M + 1, R, ql, qr); } return ret;}void UpdateInterval(int o, int L, int R, int ql, int qr){ if (ql <= L && R <= qr) { sum[o] <<= 1; maxv[o] <<= 1; mul[o]++; return; } Pushdown(o); int M = (L + R) >> 1; if (ql <= M) { UpdateInterval(lc, L, M, ql, qr); } if (qr > M) { UpdateInterval(rc, M + 1, R, ql, qr); } Maintain(o);}void UpdateLeaf(int o, int L, int R, int q, int add){ if (L == R) { sum[o] += add; maxv[o] += add; return; } Pushdown(o); int M = (L + R) >> 1; if (q <= M) { UpdateLeaf(lc, L, M, q, add); } else { UpdateLeaf(rc, M + 1, R, q, add); } Maintain(o);}void Update(int n, int l, int r, int ql, int qr){ if (ql == qr) { UpdateLeaf(1, 1, n, ql, r - l + 1); } else { int addLeft = QuerySum(1, 1, n, 1, ql) - l + 1; int addRight = r - QuerySum(1, 1, n, 1, qr - 1); UpdateLeaf(1, 1, n, ql, addLeft); UpdateLeaf(1, 1, n, qr, addRight); if (qr - ql >= 2) { UpdateInterval(1, 1, n, ql + 1, qr - 1); } }}long long QueryMax(int o, int L, int R, int ql, int qr){ if (ql <= L && R <= qr) return maxv[o]; Pushdown(o); int M = (L + R) >> 1; long long ret = 0; if (ql <= M) { ret = max(ret, QueryMax(lc, L, M, ql, qr)); } if (qr > M) { ret = max(ret, QueryMax(rc, M + 1, R, ql, qr)); } return ret;}long long Query(int n, int l, int r, int ql, int qr){ long long ret = 0; if (ql == qr) { ret = r - l + 1; } else { ret = max(ret, QuerySum(1, 1, n, 1, ql) - l + 1); ret = max(ret, r - QuerySum(1, 1, n, 1, qr - 1)); if (qr - ql >= 2) { ret = max(ret, QueryMax(1, 1, n, ql + 1, qr - 1)); } } return ret;}int main(){ int t, n, m, l, r, ql, qr, kase = 0; char op; scanf("%d", &t); getchar(); while (t--) { scanf("%d%d", &n, &m); getchar(); Build(1, 1, n); printf("Case #%d:\n", ++kase); while (m--) { op = getchar(); getchar(); l = ReadInt(); r = ReadInt(); ql = QueryFigure(1, 1, n, l); qr = QueryFigure(1, 1, n, r); if (op == 'D') { Update(n, l, r, ql, qr); } else { printf("%I64d\n", Query(n, l, r, ql, qr)); } } } return 0;}
HDU-4973-a simple simulation problem. (line segment Tree single point update + Interval Update)