zoukankan      html  css  js  c++  java
  • 2018ICPC银川 L Continuous Intervals 单调栈 线段树

    题意:给你一个序列,问你这个序列有多少个子区间,满足把区间里的数排序之后相邻两个数之间的差 <= 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);
    	}
    } 
    

      

  • 相关阅读:
    第二十九课 循环链表的实现
    第二十八课 再论智能指针(下)
    第二十七课 再论智能指针(上)
    第二十六课 典型问题分析(Bugfix)
    普通new和placement new的重载
    leetcode 581. Shortest Unsorted Continuous Subarray
    leetcode 605. Can Place Flowers
    leetcode 219. Contains Duplicate II
    leetcode 283. Move Zeroes
    leetcode 217. Contains Duplicate
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/11454221.html
Copyright © 2011-2022 走看看