思路:题解很有意思,适合线段树进阶
考虑每次修改不叠加,因此我们可以从如何对原序列进行预处理着手。
通过观察可以发现,将原序列从任意位置断开,我们可以通过分别维护左右段的某些信息来拼接
得到答案。
对于左段来说:
• 需要知道最大值的位置,以及到达最大值需要几步;
• 使用 ST 维护信息。
对于右段来说:
• 由于前半部分的信息未知,因此我们需要维护从每个位置开始到结尾可以走几步;
• 从后往前做 DP,每次找出右边第一个比自己大的数,答案就是它的 DP 值 +1。
对于每次询问:
• 考虑这个数左边的部分加上这个数之后的答案和最大值;
• 再找到右边第一个大于左半部分最大值的数,答案相加即可。
预处理使用 ST 表,每次查询需要一个二分,总复杂度 O(nlogn+qlogn)。 —题解来自HDU
#include<cstdio> #include<cmath> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define lson l,m,o<<1 #define rson m+1,r,o<<1|1 const int maxn = 1e5 + 10; int a[maxn], d1[maxn], d2[maxn]; int tree[maxn << 2], vis[maxn << 2]; int ans, cur; void build(int l, int r, int o){ if (l == r){ tree[o] = a[l]; vis[o] = l; return; } int m = (l + r) >> 1; build(lson); build(rson); tree[o] = max(tree[o << 1], tree[o << 1 | 1]); if (tree[o << 1] >= tree[o << 1 | 1]) vis[o] = vis[o << 1]; else vis[o] = vis[o << 1 | 1]; } void query(int l, int r, int o, int ql, int qr, int k){ if (l == r){ if (tree[o]>k) cur = min(cur, l); return; } int m = (l + r) >> 1; if (l >= ql&&r <= qr){ if (tree[o << 1] > k) query(lson, ql, qr, k); else if (tree[o << 1 | 1] > k) query(rson, ql, qr, k); return; } if (ql <= m) query(lson, ql, qr, k); if (qr > m)query(rson, ql, qr, k); } void query1(int l, int r, int o, int ql, int qr){ if (l >= ql&&r <= qr){ if (tree[o] > a[cur]) cur = vis[o]; return; } int m = (l + r) >> 1; if (ql <= m)query1(lson, ql, qr); if (qr > m)query1(rson, ql, qr); } int main(){ ios::sync_with_stdio(false); int t; cin >> t; while (t--){ int n, m, p, q, Max = 0; cin >> n >> m; for (int i = 1; i <= n; i++){ cin >> a[i]; if (a[i] > Max) d1[i] = d1[i - 1] + 1, Max = a[i]; else d1[i] = d1[i - 1]; } build(1, n, 1); for (int i = n; i; i--){ cur = n + 1; query(1, n, 1, i, n, a[i]); if (cur > n)cur = 0; d2[i] = d2[cur] + 1; } while (m--){ cin >> p >> q; ans = cur = 0; if (p != 1){ query1(1, n, 1, 1, p - 1); } ans += d1[cur]; if (q > a[cur])ans++; else q = a[cur]; cur = n + 1; if (p != n)query(1, n, 1, p + 1, n, q); if (cur <= n)ans += d2[cur]; cout << ans << endl; } } }