2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树)
2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树)
传送门:https://nanti.jisuanke.com/t/41296
题意:
给一个数列A
问在数列A中有多少个区间满足,区间内数字排序后是一段连续的连续的区间
即排序后区间内的任意元素满足 \(a_{i+1}-a_i<=1\)
题解:
根据题意可知
满足题意的区间应当满足以下性质:
\(max-min==num-1\)
即当前区间最大的数字减去当前区间最小的数字等于区间数字的种类数
我们枚举区间的右端点\(R_i\),那么问题就转换为了有多少个\(L_j,j<=i\)
在区间\(L_j,R_i\)中,
\(Max-Min-num==-1\)
我们需要快速的得到所有满足上式\(L_j\)的个数
也就是 我们需要快速的得到区间 \([1,R_i]\)内满足上式的个数
我们可以用线段树来维护\(Max-Min-num\)这个值
查询就查询有多少个L对应这个值,如果\(Max-Min-num==-1\)
那么对应的值的个数可以对答案产生贡献
线段树维护\(Max-Min-num\)这个值时
我们可以用两个单调栈分别维护Max和Min的值,用map来维护区间数字出现的位置
对于每一次\(Max\)值的更新来说,我们需要减去当前的最大值a[i]-要删去的值的最大值staMax[tp]
对于每一次\(Min\)值的更新来说,我们需要减去要删去的值的最小值staMin[tp]-当前的最小值a[i]
对于每一次出现的数字,他的种类数可能会改变,我们需要在他上一次出现的位置到这个位置这个区间上-1
在查询的时候,我们只需要得到对应的\(Max-Min- num\)最小值为-1的个数即可
代码:
/**
 *        ┏┓    ┏┓
 *        ┏┛┗━━━━━━━┛┗━━━┓
 *        ┃       ┃  
 *        ┃   ━    ┃
 *        ┃ >   < ┃
 *        ┃       ┃
 *        ┃... ⌒ ...  ┃
 *        ┃       ┃
 *        ┗━┓   ┏━┛
 *          ┃   ┃ Code is far away from bug with the animal protecting          
 *          ┃   ┃   神兽保佑,代码无bug
 *          ┃   ┃           
 *          ┃   ┃        
 *          ┃   ┃
 *          ┃   ┃           
 *          ┃   ┗━━━┓
 *          ┃       ┣┓
 *          ┃       ┏┛
 *          ┗┓┓┏━┳┓┏┛
 *           ┃┫┫ ┃┫┫
 *           ┗┻┛ ┗┻┛
 */
// warm heart, wagging tail,and a smile just for you!
//
//                            _ooOoo_
//                           o8888888o
//                           88" . "88
//                           (| -_- |)
//                           O\  =  /O
//                        ____/`---'\____
//                      .'  \|     |//  `.
//                     /  \|||  :  |||//  \
//                    /  _||||| -:- |||||-  \
//                    |   | \  -  /// |   |
//                    | \_|  ''\---/''  |   |
//                    \  .-\__  `-`  ___/-. /
//                  ___`. .'  /--.--\  `. . __
//               ."" '<  `.___\_<|>_/___.'  >'"".
//              | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//              \  \ `-.   \_ __\ /__ _/   .-` /  /
//         ======`-.____`-.___\_____/___.-`____.-'======
//                            `=---='
//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//                     佛祖保佑      永无BUG
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 1e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double Pi = acos(-1);
LL gcd(LL a, LL b) {
    return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b) {
    return a / gcd(a, b) * b;
}
double dpow(double a, LL b) {
    double ans = 1.0;
    while(b) {
        if(b % 2)ans = ans * a;
        a = a * a;
        b /= 2;
    } return ans;
}
LL quick_pow(LL x, LL y) {
    LL ans = 1;
    while(y) {
        if(y & 1) {
            ans = ans * x % mod;
        } x = x * x % mod;
        y >>= 1;
    } return ans;
}
/*
给你长为 1e5的数组,
要你求其中有多少个区间使得这个区间中的值域是个连续的区间,
即排序后两两个值的差小于等于1。
*/
int Min[maxn << 2];
int num[maxn << 2];
int lazy[maxn << 2];
void push_up(int rt) {
    Min[rt] = min(Min[ls], Min[rs]);
    if(Min[ls] == Min[rs]) {
        num[rt] = num[ls] + num[rs];
    } else if(Min[rt] == Min[ls]) {
        num[rt] = num[ls];
    } else {
        num[rt] = num[rs];
    }
}
void build(int l, int r, int rt) {
    Min[rt] = 0;
    lazy[rt] = 0;
    num[rt] = r - l + 1;
    if(l == r) {
        return;
    }
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
    // push_up(rt);
}
void push_down(int rt) {
    if(lazy[rt]) {
        lazy[ls] += lazy[rt];
        lazy[rs] += lazy[rt];
        Min[ls] += lazy[rt];
        Min[rs] += lazy[rt];
        lazy[rt] = 0;
    }
}
void update(int L, int R, int val, int l, int r, int rt) {
    if(L <= l && r <= R) {
        Min[rt] += val;
        lazy[rt] += val;
        return;
    }
    push_down(rt);
    int mid = (l + r) >> 1;
    if(L <= mid) update(L, R, val, lson);
    if(R > mid) update(L, R, val, rson);
    push_up(rt);
}
pii query(int L, int R, int l, int r, int rt) {
    if(L <= l && r <= R) {
        return make_pair(Min[rt], num[rt]);
    }
    push_down(rt);
    int mid = (l + r) >> 1;
    pii tmp1 = make_pair(INF, 0), tmp2 = make_pair(INF, 0);
    if(L <= mid) {
        tmp1 = query(L, R, lson);
    }
    if(R > mid) {
        tmp2 = query(L, R, rson);
    }
    pii ans;
    if(tmp1.first == tmp2.first) {
        ans = make_pair(tmp1.first, tmp1.second + tmp2.second);
        return ans;
    }
    if(tmp1.first < tmp2.first) {
        ans = tmp1;
        return ans;
    } else {
        ans = tmp2;
        return ans;
    }
    return ans;
}
int a[maxn];
pii Maxsta[maxn], Minsta[maxn];
map<int, int>mp;
int main() {
#ifndef ONLINE_JUDGE
    FIN
#endif
    int T;
    scanf("%d", &T);
    int cas = 1;
    while(T--) {
        int n;
        int tpMax = 0;
        int tpMin = 0;
        scanf("%d", &n);
        build(1, n, 1);
        mp.clear();
        LL ans = 0;
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
        for(int i = 1; i <= n; i++) {
            // mp[a[i]] = i;
            while(tpMax > 0 &&  Maxsta[tpMax].first < a[i]) {
                //减去小于当前值的Max贡献
                update(Maxsta[tpMax - 1].second + 1, Maxsta[tpMax].second, a[i] - Maxsta[tpMax].first, 1, n, 1);
                tpMax--;
            }
            Maxsta[++tpMax] = make_pair(a[i], i);
            while(tpMin > 0 && Minsta[tpMin].first > a[i]) {
                //减去大于当前值的Min贡献
                update(Minsta[tpMin - 1].second + 1, Minsta[tpMin].second, Minsta[tpMin].first - a[i], 1, n, 1);
                tpMin--;
            }
            Minsta[++tpMin] = make_pair(a[i], i);
            //减去重复数字的贡献
            update(mp[a[i]] + 1, i, -1, 1, n, 1);
            mp[a[i]] = i;
            pii flag = query(1, i, 1, n, 1);
            if(flag.first == -1) {
                ans += flag.second;
            }
        }
        printf("Case #%d: %lld\n", cas++, ans);
    }
    return 0;
}
2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树)的更多相关文章
- 2018ICPC银川 L Continuous Intervals 单调栈 线段树
		题意:给你一个序列,问你这个序列有多少个子区间,满足把区间里的数排序之后相邻两个数之间的差 <= 1 ? 思路:https://blog.csdn.net/u013534123/article/ ... 
- 2018宁夏邀请赛L Continuous Intervals
		题目链接:https://nanti.jisuanke.com/t/28412 题意: 给出n个数的序列.问序列中有多少个区间满足,排序完之后任意两个相邻的数之差不大于1. 题解: 用max表示区间最 ... 
- 2018宁夏邀请赛 L. Continuous Intervals
		转化一下询问即为区间$max - min + 1 = cnt$,其中$cnt$表示区间内数的种类数. 即求有多少区间$max - min - cnt=-1$,注意到任意区间的$max-min-cnt ... 
- 南昌邀请赛I.Max answer 单调栈+线段树
		题目链接:https://nanti.jisuanke.com/t/38228 Alice has a magic array. She suggests that the value of a in ... 
- 洛谷P4198 楼房重建 单调栈+线段树
		正解:单调栈+线段树 解题报告: 传送门! 首先考虑不修改的话就是个单调栈板子题昂,这个就是 然后这题的话,,,我怎么记得之前考试好像有次考到了类似的题目昂,,,?反正我总觉着这方法似曾相识的样子,, ... 
- 2018宁夏邀请赛 Continuous Intervals(单调栈 线段树
		https://vjudge.net/problem/Gym-102222L 题意:给你n个数的序列,让判断有几个区间满足排完序后相邻两数差都不大于1. 题解:对于一个区间 [L,R],记最大值为 m ... 
- 2019ICPC南昌邀请赛网络赛 I. Max answer (单调栈+线段树/笛卡尔树)
		题目链接 题意:求一个序列的最大的(区间最小值*区间和) 线段树做法:用单调栈求出每个数两边比它大的左右边界,然后用线段树求出每段区间的和sum.最小前缀lsum.最小后缀rsum,枚举每个数a[i] ... 
- The Preliminary Contest for ICPC China Nanchang National Invitational I. Max answer  (单调栈+线段树)
		题目链接:https://nanti.jisuanke.com/t/38228 题目大意:一个区间的值等于该区间的和乘以区间的最小值.给出一个含有n个数的序列(序列的值有正有负),找到该序列的区间最大 ... 
- 2019南昌网络赛-I(单调栈+线段树)
		题目链接:https://nanti.jisuanke.com/t/38228 题意:定义一段区间的值为该区间的和×该区间的最小值,求给定数组的最大的区间值. 思路:比赛时还不会线段树,和队友在这题上 ... 
随机推荐
- Codeforces 425B
			点击打开题目链接 题意:给定一个n×m的0,1矩阵,做多可以对矩阵做k次变换,每次变换只可以将矩阵的某一个元素由0变成1,或从1变成0. 求最小的变换次数使得得到的矩阵满足:每一个连通块都是一个“实心 ... 
- RedHat6.2离线安装vncserver
			准备安装包 tigervnc-server-1.1.0-5.el6_4.1.x86_64.rpm pixman-0.32.8-1.el6.x86_64.rpm pixman-devel-0.32.8- ... 
- AtCoder Beginner Contest 064 D - Insertion
			AtCoder Beginner Contest 064 D - Insertion Problem Statement You are given a string S of length N co ... 
- 从入侵到变现——“黑洞”下的黑帽SEO分析
			概述 由于互联网入口流量主要被搜索引擎占据,网站在搜索引擎中的排名直接影响到市场营销效果,因此SEO服务应运而生.SEO(Search Engine Optimization)全称为搜索引擎优化,是指 ... 
- 关于取List中的指定几条数据以及注意事项
			list1 = list2.subList(start, end); start,end分别是第几个到第几个. 注意的是此方法和substring一样,包含前不包含结尾,取下标索引 另一个注意的地方是 ... 
- win10 uwp 使用动画修改 Grid column 的宽度
			今天 wurstmitbrot 问如何通过动画修改 Grid 的 column ,虽然 column 是一个依赖属性,可以绑定,但是做出动画还是比较难的. 本文告诉大家如何对 Grid 做动画. 首先 ... 
- POJ-3615_Cow Hurdles
			Cow Hurdles Time Limit: 1000MS Memory Limit: 65536K Description Farmer John wants the cows to prepar ... 
- @bzoj - 4378@ [POI2015] Logistyka
			目录 @description@ @solution@ @accepted code@ @details@ @description@ 维护一个长度为 n 的序列,一开始都是 0,支持以下两种操作: ... 
- uni-app原生导航栏使用iconfont图标
			在 iconfont 将图标下载之后,会有一个 .ttf 后缀的文件 把它放进 static 文件夹里 然后打开在iconfont下载的 demo_index.html 文件 选择 Unicode ... 
- W3C vs IE盒模型
			今年4月份的一次面试,问到盒模型,是我第一次接触到盒模型,但当时不太明白,没有说清楚,后来查了下,但一知半解. 下面分享下,我对盒模型的理解: 盒模型,也就是box-sizing,分为content- ... 
