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);
    	}
    } 
    

      

  • 相关阅读:
    java面试②基础部分
    java面试①整体流程
    Mysql加锁过程详解(6)-数据库隔离级别(2)-通过例子理解事务的4种隔离级别
    Mysql加锁过程详解(6)-数据库隔离级别(1)
    CV3——学习笔记-实战项目(上):如何搭建和训练一个深度学习网络
    CV2——学习笔记-图像分类
    CV1——学习笔记
    思无邪
    C++学习笔记
    操作系统——学习笔记
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/11454221.html
Copyright © 2011-2022 走看看