2018icpc宁夏邀请赛_L_Continuous Intervals
题意
给定一个序列,定义连续区间为区间的数排序后,任意两个相邻的数之差不超过1。
分析
- 假设区间最大值为\(max\),最小值为\(min\),不同数个数为\(cnt\),那么问题转化为求满足\(max-min-cnt==1\)的区间个数。
- 统计满足条件的区间个数可以考虑用线段树,主要有三个步骤:
- 枚举右端点\(R\)
- 线段树维护当前所有左端点,即每个叶子节点\((i,i)\),表示序列区间\([i,R]\)
- 统计答案,以\(R\)为右端点的所有区间,即线段树根节点\((1,n)\)
- 更新区间分为两部分
- 第一部分是\(cnt\),也相当于也就是要更新当前\(R\),前面有多少个区间\([i,R]\)以\(a[R]\)作为一个新的不同的数字,显然就是\(a[R]\)上一次出现的位置+1,因为公式中是\(-cnt\),所以更新值为-1。
- 第二部分是\(max\)和\(min\),利用单调栈来维护,当从栈中弹出时,可以得到该元素作为最大/最小值延伸的区间,更新值就是该元素和新的最大/最小值\(a[R]\)之间的差值。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+50;
const int INF=0x3f3f3f3f;
int T,n,a[N];
//线段树(1-n)维护的是当前R作为右端点,([1,R],[2,R]...[R,R])这些区间的情况,也就是一个点代表一个区间
struct ST{
#define ls i<<1
#define rs i<<1|1
#define mid (l+r)/2
//维护区间(mx-mn-cnt)的最小值和最小值的个数
int sm[N*4],mn[N*4],lz[N*4];
void pushup(int i){
mn[i]=min(mn[ls],mn[rs]);
if(mn[ls]==mn[rs]){
sm[i]=sm[ls]+sm[rs];
}else if(mn[ls]<mn[rs]){
sm[i]=sm[ls];
}else{
sm[i]=sm[rs];
}
}
void pushdown(int i){
if(lz[i]){
lz[ls]+=lz[i];
lz[rs]+=lz[i];
mn[ls]+=lz[i];
mn[rs]+=lz[i];
lz[i]=0;
}
}
void build(int i,int l,int r){
lz[i]=0;
if(l==r){
mn[i]=INF;
sm[i]=0;
return;
}
build(ls,l,mid);
build(rs,mid+1,r);
pushup(i);
}
//单点插入/修改,即开始增加以p为左端点的区间贡献
void insert(int i,int l,int r,int p){
if(l==r){
//此时以p为左端点的区间只有[p,p],因此mx-mn-cnt=-1,为合法区间
mn[i]=-1;
sm[i]=1;
return;
}
pushdown(i);
if(p<=mid){
insert(ls,l,mid,p);
}else{
insert(rs,mid+1,r,p);
}
pushup(i);
}
//区间更新(mx-mn-cnt)
void update(int i,int l,int r,int ql,int qr,int v){
if(ql<=l && qr>=r){
lz[i]+=v;
mn[i]+=v;
return;
}
pushdown(i);
if(ql<=mid){
update(ls,l,mid,ql,qr,v);
}
if(qr>mid){
update(rs,mid+1,r,ql,qr,v);
}
pushup(i);
}
}ac;
map<int,int> lst;
int smx[N],smn[N];
int main(){
// freopen("in.txt","r",stdin);
scanf("%d",&T);
for(int cas=1;cas<=T;cas++){
ll ans=0;
scanf("%d",&n);
ac.build(1,1,n);
lst.clear();
int mxt=0,mnt=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
ac.insert(1,1,n,i);
//单调栈维护最大最小值区间
//维护一个小顶栈,那么弹出来的元素作为最大值延伸的位置是[smx[mxt-1]+1,smx[mxt]]
while(mxt>0 && a[smx[mxt]]<=a[i]){
ac.update(1,1,n,smx[mxt-1]+1,smx[mxt],a[i]-a[smx[mxt]]);
mxt--;
}
smx[++mxt]=i;
while(mnt>0 && a[smn[mnt]]>=a[i]){
ac.update(1,1,n,smn[mnt-1]+1,smn[mnt],-(a[i]-a[smn[mnt]]));
mnt--;
}
smn[++mnt]=i;
//map维护上一次出现位置
int L=0;
if(lst.find(a[i])!=lst.end()){
L=lst[a[i]]+1;
}else{
L=1;
}
if(L<=i-1){
//比如3 1 2 4 3,最新加入的3,所以[1 2 4 3],[2 4 3],[4 3]都应该更新不同数的个数
//由于维护的是mx-mn-cnt,所以是-1
ac.update(1,1,n,L,i-1,-1);
}
lst[a[i]]=i;
//以当前a[i]为右端点元素的合法区间个数
//因为加入新节点(R,R)后,mn[1]肯定为-1,所以无需判断
ans+=1ll*ac.sm[1];
}
printf("Case #%d: %lld\n",cas,ans);
}
}
2018icpc宁夏邀请赛_L_Continuous Intervals的更多相关文章
- 2018宁夏邀请赛 Continuous Intervals(单调栈 线段树
https://vjudge.net/problem/Gym-102222L 题意:给你n个数的序列,让判断有几个区间满足排完序后相邻两数差都不大于1. 题解:对于一个区间 [L,R],记最大值为 m ...
- 2018icpc宁夏邀请赛网络赛_G_Trouble of Tyrant
题意 一列\(n\)个点,给定一个特殊的图,有两种边\(E(1,i)\)和\(E(i-1,i)\),多个询问,每次给一个\(d\),求所有路径长度加上\(d\)后1到\(n\)的最短路. 分析 首先这 ...
- 2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树)
2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树) 传送门:https://nanti.jisuanke.com/t/41296 题意: 给一个数列A 问在数列A中有多 ...
- [ICPC 2018 宁夏邀请赛] A-Maximum Element In A Stack(思维)
>传送门< 前言 辣鸡网络赛,虽然我是个菜鸡,然而好几个队伍十几分钟就AK???我心态那会彻底崩了,后来群里炸了,话题直接上知乎热搜,都是2018ICPC宁夏网络赛原题,这怎么玩,拼手速? ...
- 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 ...
- 2018acm-icpc宁夏邀请赛后记
由于要准备期末考试的缘故,时隔一个月之后我才想起来还有一场比赛没有总结. 大概是出去过的最远的地方了,宁夏理工学院离杭州有两千多千米. 不得不说感到了主办方满满的诚意,虽然是第一次办比赛,但是第一天组 ...
- 2018宁夏邀请赛网赛 I. Reversion Count(java练习题)
题目链接 :https://nanti.jisuanke.com/t/26217 Description: There is a positive integer X, X's reversion c ...
- “2018宁夏邀请赛 ” 兼 “The 2019 Asia Yinchuan First Round Online Programming”
------------7题弟弟,被各位半小时13题的大佬打惨了(滑稽)---------- 签到题就不写了. F :Moving On (1247ms) 题意:给定大小为N的带 ...
随机推荐
- (LeetCode)1114. 按序打印
题目来源:https://leetcode-cn.com/problems/print-in-order/ 我们提供了一个类: public class Foo { public void one( ...
- Java中FileOutputStream流的write方法
本文为大家分享了FileOutputStream流的write方法,供大家参考,具体内容如下 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...
- LocalDateTime自动转化格式
开发中,遇到这样的问题.一个LocalDateTime类型的属性返回给前端是中间带T的格式,前端说转不了. 可以引入jackson包转换一下 <properties> <jackso ...
- php面向对象 练习
实例一:求一个圆环的面积,大圆半径:10 小圆半径:5 造一个圆的类: class Yuan { public $r; function __construct($r) //半径初始化 { $t ...
- 非均匀B样条离散点的加密与平滑
非均匀B样条离散点的加密与平滑 离散点的预处理是点云网格化很关键的一步,主要就是离散点的平滑.孔洞修补:本文是基于非均匀B样条基函数进行离散点云的加密和平滑的,一下为初步实现结果. 算法步骤: 1.数 ...
- sorted&filter&map
python里列表的sort和内置的sorted函数,都可以进行排序,列表的sort方法是在原有的列表上进行排序,sorted是会返回一个新的对象 persons = [ {'name': '小明', ...
- 【Java基础】JAVA 使用线程的几种方式
之前放在自己网站上的例子,因为网站关闭,已经找不到了,想用的时候,没有的话又重新翻书是很麻烦的事情.所以重新记录一下,以备将来查看. 第一种,让任务类继承Runable接口,然后将任务类对象放入Thr ...
- 深入理解Istio核心组件之Pilot
Istio作为当前服务网格(Service Mesh)领域的事实标准,流量治理(Traffic Management)是其最为基础也最为重要的功能.本文将结合源码对Istio流量治理的实现主体——组件 ...
- select去掉默认样式
今天遇到的问题,并在这里做一下记录和总结 去除select下拉框默认样式 select { /*Chrome和Firefox里面的边框是不一样的,所以复写了一下*/ border: solid 1px ...
- Java多线程ThreadLocal介绍
在Java多线程环境下ThreadLocal就像一家银行,每个线程就是银行里面的一个客户,每个客户独有一个保险箱来存放金钱,客户之间的金钱不影响. private static ThreadLocal ...