51Nod-1810-连续区间
2017-07-30 00:56
232 查看
ACM模版
这里详细的题解我就贴一下官方题解吧,官方题解说的十分详细,我也不用多费口舌了……
描述
题解
这个题需要用到分治的思想,最最最重要的一个问题是,合法的连续区间有什么充要条件?这个不难想,某一个区间的最大值和最小值的差加一一定是这个区间的元素个数时才是合法的,因为题中说了,这是 1∼n 的排列,所以不存在重复,而每个相邻的又刚好差 1,那么很明显,上述条件一定成立!这里详细的题解我就贴一下官方题解吧,官方题解说的十分详细,我也不用多费口舌了……
代码
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int MAXN = 1e6 + 5; int n; ll ans = 0; int a[MAXN]; int b[MAXN << 2]; int mx[MAXN]; int mn[MAXN]; template <class T> inline void scan_d(T &ret) { char c; ret = 0; while ((c = getchar()) < '0' || c > '9'); while (c >= '0' && c <= '9') { ret = ret * 10 + (c - '0'), c = getchar(); } } void solve(int l, int r) { int m = (l + r) / 2; mx[m] = mn[m] = a[m]; for (int i = m - 1; i >= l; i--) { mx[i] = max(a[i], mx[i + 1]); mn[i] = min(a[i], mn[i + 1]); } mx[m + 1] = mn[m + 1] = a[m + 1]; for (int i = m + 2; i <= r; i++) { mx[i] = max(a[i], mx[i - 1]); mn[i] = min(a[i], mn[i - 1]); } for (int i = m; i >= l; i--) { int j = i + mx[i] - mn[i]; if (j > m && j <= r && mx[i] > mx[j] && mn[i] < mn[j]) { ans++; } } for (int i = m + 1; i <= r; i++) { int j = i - (mx[i] - mn[i]); if (j >= l && j <= m && mx[j] < mx[i] && mn[j] > mn[i]) { ans++; } } // 确定左边包含最大查右边最小范围 int l_ = m + 1, r_ = m; for (int i = m; i >= l; i--) { while (r_ < r && mx[r_ + 1] < mx[i]) { r_++; b[mn[r_] + r_ + MAXN]++; } while (l_ <= r_ && mn[l_] > mn[i]) { b[mn[l_] + l_ + MAXN]--; l_++; } ans += b[mx[i] + i + MAXN]; } while (l_ <= r_) { b[mn[l_] + l_ + MAXN]--; l_++; } // 确定右边包含最大查左边最小范围 l_ = m + 1, r_ = m; for (int j = m + 1; j <= r; j++) { while (l_ > l && mx[l_ - 1] < mx[j]) { l_--; b[mn[l_] - l_ + MAXN]++; } while (r_ >= l_ && mn[r_] > mn[j]) { b[mn[r_] - r_ + MAXN]--; r_--; } ans += b[mx[j] - j + MAXN]; } while (l_ <= r_) { b[mn[r_] - r_ + MAXN]--; r_--; } if (l == r) { ans++; return ; } solve(l, m); solve(m + 1, r); } int main() { scan_d(n); for (int i = 1; i <= n; i++) { scan_d(a[i]); } solve(1, n); printf("%lld\n", ans); return 0; }
相关文章推荐
- 51NOD 1810 连续区间 分治 区间计数
- 51nod 1810 连续区间
- 51nod 1810 连续区间(分治)
- 51Nod 1094 和为k的连续区间 | 水
- 51nod 1094 和为k的连续区间 map优化
- 51Nod 1094 和为k的连续区间 map
- 51nod-1094 和为k的连续区间
- 51Nod 1094 和为k 的连续区间 题解
- 51nod-【1094 和为k的连续区间】
- 51Nod-1094-和为k的连续区间
- 51nod 1094 和为k的连续区间
- 51NOD 1094 和为k的连续区间(前缀和 + map)
- 51nod 1393 0和1相等串 (连续区间)
- 51nod 1094 和为k的连续区间
- 51nod 1094 和为k的连续区间
- 51nod 1094 和为k的连续区间(暴力和map优化)
- 51nod 1062 序列中最大的数 (打表,连续区间问题)
- 51nod 1094 和为k的连续区间 (暴力||map数组优化)
- 51nod-- 1094 和为k的连续区间
- 51Nod 1094 和为k的连续区间