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的带 ...
随机推荐
- lcez校内模拟赛: 小R与苹果派——题解
题目传送 首先对两个数组排序. 然后预处理出数组p[i]表示b[x]<a[i]的最大的x. 然后我们设f[i][k]表示对于前i个派,我单独选出来k组a[y]>b[y].(即此时有k组a& ...
- 实现shape图层添加label
void CmapwingisTest2View::OnToolsAdd32780() { TCHAR szFilters[]= _T("SHP Files (*.shp)|*.shp||& ...
- io.h配置 ubuntu
https://www.cnblogs.com/liuyangak/articles/3239238.html https://blog.csdn.net/jiao_mrswang/article/d ...
- JavaScript getClass() 函数
定义和用法 getClass() 函数可返回一个 JavaObject 的 JavaClass. 语法 getClass(javaobj) 参数 描述 javaobj 一个 JavaObject 对象 ...
- java 中的多态
多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,就是同一种事物表现出的多种形态. 下面利用代码进行简单概述: 实现多态必须要满足三个条件 1必须有继承 2必须重写 3必须父类引用子类对象 ...
- hadoop 配置注意
到目前为止,关于配置1.*版本的hadoop书籍占多数,前面配置2.*失败以后照着书籍配置1.2.1成功. 准备工具:(注意用统一位数的,我的64位) hadoop1.2.1 jdk1.6 xshel ...
- Android的工程目录主要有哪些
src 源文件gen 生成的文件 R 文件就在此android. jar 依赖的 android sdkassets 资源文件bin 生成的字节码 apk 在此libs 依赖 jar 和 sores ...
- Word模板替换
package com.sisa.auweb.tools.bookmarkprocess; import org.apache.poi.openxml4j.opc.OPCPackage; import ...
- LVS 四层 TCP/UDP 负载均衡器
目录 文章目录 目录 LVS LVS 应用结构 LVS 提供的三种模式 LVS-NAT LVS-TUN LVS_DR LVS 负载均衡算法 静态负载均衡 动态负载均衡 LVS-ipvsadm 指令集 ...
- vc/vs常见报错:/****error C2106: '=' : left operand must be l-value****/
一.错误信息解析: 1.error,表示这是一条出错信息. C语言信息一般有error(出错)和warning(警告)两种. error是编译器遇到了致命错误,无法继续进行编译,必须修改. warni ...