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的带 ...
随机推荐
- 【UTR #3】量子破碎
一道有趣的题. 看到按位的矩阵运算,如果对FWT比较熟悉的话,会比较容易地想到. 这种形式也就FWT等转移里面有吧--就算有其他的也难构造出来. 然而FWT的矩阵并不是酉矩阵(也就是满足 \(AA^T ...
- Luogu P4707 重返现世 (拓展Min-Max容斥、DP)
题目链接 https://www.luogu.org/problem/P4707 题解 最近被神仙题八连爆了-- 首先Min-Max容斥肯定都能想到,问题是这题要用一个扩展版的--Kth Min-Ma ...
- (转译)2019年WEB漏洞扫描工具和软件前十名推荐
这些工具都有助于发现漏洞,从而最大限度地提高测试人员的时间和效率.这些工具,2019年更新,也可用于寻找漏洞. 为何扫描? 这资源是什么? Web应用程序对黑客具有极大的吸引力,并且出于百万种不同的原 ...
- 两种建立堆的方法HeapInsert & Heapify
参考 堆排序中两种建堆方法的比较 第一种方法HeapInsert 它可以假定我们事先不知道有多少个元素,通过不断往堆里面插入元素进行调整来构建堆. 它的大致步骤如下: 首先增加堆的长度,在最末尾的地方 ...
- shell脚本之for 列表循环
作用:对列表进行循环处理 语法: for var in list do commands done 案例: 1.读取列表中的值 2.读取列表中的复杂值 异常案例:未显示出“'”单引号,使语句出现异常 ...
- JavaEE-实验二 Java集合框架实验
该博客仅专为我的小伙伴提供参考而附加,没空加上代码具体解析,望各位谅解 1. 使用类String类的分割split 将字符串 “Solutions to selected exercises ca ...
- 修改主机名、hosts解析记录
.hostname和hosts的区别 /etc/hostname中存放的是主机名 /etc/hosts存放的是域名与ip的对应关系 .修改主机名 需要下面两个步骤的结合才可以 2.1.修改网络主机名 ...
- 原生dapper中新增用户后根据用户id,在用户角色表中添加关联数据,事务处理
var result = 0; var userId = 0; using (var db = _Sql.Connection) using (var tran =db.BeginTransactio ...
- java:常用类(包装类,equals和==的比较,Date,java.lang.String中常用方法,枚举enum)
*包装类: 将基本类型封装成类,其中包含属性和方法以方便对象操作. *byte---->Byte *short--->Short *long--->Long *float---> ...
- Unity中的动画系统和Timeline(4) AvatarMask和IK动画
AvatarMask(骨骼遮罩) 在前面角色动画的基础上,角色在奔跑过程中捡起一块木头,双手要抱着这块木头.如果使用前面的方法,直接切换动画,那么就只剩下抱木头的动画,其它动画就没了.这时我们要使用下 ...