2018ICPC银川 L Continuous Intervals 单调栈 线段树

题意:给你一个序列,问你这个序列有多少个子区间,满足把区间里的数排序之后相邻两个数之间的差 <= 1 ? 

思路:https://blog.csdn.net/u013534123/article/details/81164504

代码:

#include 
#define INF 0x3f3f3f3f
#define ls (o << 1)
#define rs (o << 1 | 1)
#define pii pair
#define LL long long
using namespace std;
const int maxn = 100010;
map 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 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\n", ++kase, ans);
	}
} 

  

你可能感兴趣的:(2018ICPC银川 L Continuous Intervals 单调栈 线段树)