题意:给你一个序列,问你这个序列有多少个子区间,满足把区间里的数排序之后相邻两个数之间的差 <= 1 ?
思路:https://blog.csdn.net/u013534123/article/details/81164504
代码:
#include <bits/stdc++.h> #define INF 0x3f3f3f3f #define ls (o << 1) #define rs (o << 1 | 1) #define pii pair<int, int> #define LL long long using namespace std; const int maxn = 100010; map<int, int> last; struct node { int mi, add, cnt; }; node tr[maxn * 4]; void maintain(pii& t1, pii t2) { if(t1.first > t2.first) { t1 = t2; } else { t1.second += t2.second; } } void pushup(int o) { if(tr[ls].mi < tr[rs].mi) { tr[o].mi = tr[ls].mi; tr[o].cnt = tr[ls].cnt; } else if(tr[ls].mi > tr[rs].mi) { tr[o].mi = tr[rs].mi; tr[o].cnt = tr[rs].cnt; } else { tr[o].mi = tr[ls].mi; tr[o].cnt = tr[ls].cnt + tr[rs].cnt; } } void pushdown(int o) { if(tr[o].add) { tr[ls].mi += tr[o].add; tr[ls].add += tr[o].add; tr[rs].add += tr[o].add; tr[rs].mi += tr[o].add; tr[o].add = 0; } } void build(int o, int l, int r) { tr[o].mi = tr[o].add = tr[o].cnt = 0; if(l == r) { tr[o].cnt = 1; return; } int mid = (l + r) >> 1; build(ls, l, mid); build(rs, mid + 1, r); pushup(o); } void update(int o, int l, int r, int ql, int qr, int val) { if(l >= ql && r <= qr) { tr[o].add += val; tr[o].mi += val; return; } pushdown(o); int mid = (l + r) >> 1; if(ql <= mid) update(ls, l, mid, ql, qr, val); if(qr > mid) update(rs, mid + 1, r, ql, qr, val); pushup(o); } pii query(int o, int l, int r, int ql, int qr) { if(l >= ql && r <= qr) { return make_pair(tr[o].mi, tr[o].cnt); } int mid = (l + r) >> 1; pushdown(o); pii ans = make_pair(INF, 0); if(ql <= mid) maintain(ans, query(ls, l, mid, ql, qr)); if(qr > mid) maintain(ans, query(rs, mid + 1, r, ql, qr)); return ans; } stack<int> mi, mx; int a[maxn]; int main() { int T, n; LL ans = 0; int kase = 0; scanf("%d", &T); while(T--) { scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); } // memset(tr, 0, sizeof(tr)); build(1, 1, n); last.clear(); ans = 0; while(mi.size())mi.pop(); while(mx.size())mx.pop(); mx.push(0), mi.push(0); for (int i = 1; i <= n; i++) { // update(1, 1, n, i, i, a[i]); int now = i - 1; while(mx.size() > 1 && a[mx.top()] <= a[i]) { int tmp = mx.top(); mx.pop(); update(1, 1, n, mx.top() + 1, now, a[i] - a[tmp]); now = mx.top(); } mx.push(i); // update(1, 1, n, i, i, -a[i]); now = i - 1; while(mi.size() > 1 && a[mi.top()] >= a[i]) { int tmp = mi.top(); mi.pop(); update(1, 1, n, mi.top() + 1, now, a[tmp] - a[i]); now = mi.top(); } mi.push(i); update(1, 1, n, last[a[i]] + 1, i, -1); last[a[i]] = i; pii tmp = query(1, 1, n, 1, i); if(tmp.first == -1) { ans += tmp.second; } } printf("Case #%d: %lld ", ++kase, ans); } }