题目链接:点击查看

题目大意:给出一个 1 ~ n 的排列 a ,现在规定骚区间当且仅当 a[ l ] 是 [ l , r ] 这段区间内的次小值,同时 a[ r ] 是 [ l , r ] 这段区间内的次大值,现在问有多少个子区间(连续)是sao的

题目分析:一段对两个端点都有约束的区间,在确定下来一个端点后,根据条件不难确定出另一个端点的可行范围

但为了确定有多少左右区间可以配对,我们可以利用线段树和扫描线的思想进行维护

枚举端点 i 作为左端点时,找到右端点的可行区间 [ l , r ] ,将点 l 的标记打上 { i , 1 } ,点 r + 1 的标记打上 { i , - 1 }

然后更新点 i 的标记到线段树上,如果标记的第二个值为 1 ,说明将第一个添加到线段树上,- 1 代表删除

最后令点 i 作为右端点,找到左端点的可行区间 [ L , R ] ,在线段树上统计区间 [ L , R ] 内有多少个数,就说明有多少个数可以在点 i 作为右端点时,作为左端点与其匹配

只是单纯的一种可以解决对区间两个端点存在约束的配对问题的方法,实现起来的话线段树也可以用树状数组代替,时间复杂度 nlogn

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e6+100;vector<int>pos[N];int c[N],cnt[N],a[N],n;int lowbit(int x)
{return x&(-x);
}void update(int pos,int val)
{while(pos<N){c[pos]+=val;pos+=lowbit(pos);}
}int query(int pos)
{int ans=0;while(pos){ans+=c[pos];pos-=lowbit(pos);}return ans;
}struct Node
{int l,r;int mmin,mmax;
}tree[N<<2];void pushup(int k)
{tree[k].mmin=min(tree[k<<1].mmin,tree[k<<1|1].mmin);tree[k].mmax=max(tree[k<<1].mmax,tree[k<<1|1].mmax);
}void build(int k,int l,int r)
{tree[k].l=l;tree[k].r=r;if(l==r){tree[k].mmax=tree[k].mmin=a[l];return;}int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);pushup(k);
}int query_min(int k,int l,int r,int val)//返回区间[l,r]内小于val的最小位置
{if(l>r)return n+1;if(tree[k].l>r||tree[k].r<l)return n+1;if(tree[k].mmin>=val)return n+1;if(tree[k].l==tree[k].r)return tree[k].l;int temp=query_min(k<<1,l,r,val);if(temp!=n+1)return temp;return query_min(k<<1|1,l,r,val);
}int query_max(int k,int l,int r,int val)//返回区间[l,r]内大于val的最大位置
{if(l>r)return 0;if(tree[k].l>r||tree[k].r<l)return 0;if(tree[k].mmax<=val)return 0;if(tree[k].l==tree[k].r)return tree[k].l;int temp=query_max(k<<1|1,l,r,val);if(temp!=0)return temp;return query_max(k<<1,l,r,val);
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",a+i);build(1,1,n);LL ans=0;for(int i=1;i<=n;i++){int l=query_min(1,i,n,a[i]),r=query_min(1,l+1,n,a[i]);pos[l].push_back(i);pos[r].push_back(-i);for(auto v:pos[i]){if(v>0){if(cnt[v]==0)update(v,1);cnt[v]++;}else{cnt[-v]--;if(cnt[-v]==0)update(-v,-1);}}r=query_max(1,1,i,a[i]),l=query_max(1,1,r-1,a[i]);ans+=query(r)-query(l);}printf("%lld\n",ans);return 0;
}

牛客 - 骚区间(线段树+思维)相关推荐

  1. 牛客 - 求函数(线段树+区间合并/线段树+矩阵维护)

    题目链接:点击查看 题目大意:现在有 n 个函数,每个函数都是诸如 f( x ) = k * x + b 的形式,只是每个函数的 k 和 b 都是相互独立的,现在给出两个操作: 1 pos k b:将 ...

  2. 51NOD 1631 小鲨鱼在51nod小学 区间线段树

    1631 小鲨鱼在51nod小学 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 收藏 关注 鲨鱼巨巨2.0(以下简称小鲨鱼)以优异的成绩考入了51nod小学.并依 ...

  3. 2021牛客暑期多校训练营1 J-Journey among Railway Stations(线段树+思维转化)

    J-Journey among Railway Stations 注意区间合并时是否可行信息的合并. 假设线段树当前左节点lll维护的区间是[L,mid][L,\text{mid}][L,mid],右 ...

  4. 牛客 - sequence(笛卡尔树+线段树)

    题目链接:点击查看 题目大意:给出一个长度为 n 的数列 a 和数列 b ,求 题目分析:不算难的题目,对于每个 a[ i ] 求一下贡献然后维护最大值就好,具体思路就是,先找出每个 a[ i ] 左 ...

  5. 小翔和泰拉瑞亚(线段树+思维)

    链接:https://ac.nowcoder.com/acm/contest/3566/D 来源:牛客网 小翔和泰拉瑞亚 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K ...

  6. Codeforces 1108 E2(线段树+思维)

    传送们 题意: 给你一个长度为nnn的数列bbb.以及mmm个区间. 你可以选取111个或多个这样的区间aia_iai​,使得令区间aia_iai​所对应的所有值bib_ibi​都减111.你最终要使 ...

  7. CodeForces - 1405E Fixed Point Removal(线段树+思维)

    题目链接:点击查看 题目大意:给出一个长度为 n 的数列 a ,规定当 a[ i ] == i 时,位置 i 可以被删除掉,后面位置会合并上来,现在需要回答 m 次询问,每次询问会问禁用掉后面 x 个 ...

  8. HDU - 6602 Longest Subarray(线段树+思维)

    题目链接:点击查看 题目大意:给出一个长度为 n 的序列,每个数字的范围是 [ 1 , C ] ,现在需要求一个子串,使得字串中的字母,要么出现 0 次,要么出现至少 K 次,问这个子串的最大长度是多 ...

  9. HDU - 6315 Naive Operations(线段树+思维)

    题目链接:点击查看 题目大意:给出一个数列 a 和一个数列 b ,其中数列 a 初始时全部为 0 ,数列 b 初始时是一个 1 ~ n 的排列,接下来共有 m 次操作,每次操作分为两种: add l ...

最新文章

  1. DotNet 项目开发文档的自动生成和相关工具的使用
  2. 如何为linux释放内存和缓存
  3. 科大讯飞AIUI(1)
  4. 关于线程池ExecutorService的shutdown()与shutdownNow()方法的区别
  5. c语言1到20找最大和最小相邻,一组数据里面怎样查找相邻和相同的整数算法设计解决方案...
  6. OpenCASCADE:Open CASCADE Application Framework (OCAF)的简介
  7. [Machine learning] 国外程序员整理的机器学习资源大全
  8. bootstrap 模态框满屏_解决Ueditor在bootstarp 模态框中全屏问题
  9. 后端技术:Java程序员常用的11个API,你都知道吗?
  10. 人工智能AI实战100讲(十)-一文读懂推荐系统负采样
  11. kmem 反编译linux内核_24小时学通Linux内核之如何处理输入输出操作
  12. 摄影毁一生单反穷三代顺口溜_哪款便宜的单反相机好
  13. python瓦登尔湖词频统计
  14. 群晖docker火狐_群晖 篇一:群晖Docker下搭建ubuntu开发环境
  15. 一年白干!程序员赵某仿制老东家APP,获取服务器数据,被判4年6个月
  16. 商标注册需要多久下证
  17. C++ thread用法总结(整理)
  18. Paint in 3D 基本使用方法(Unity 3D)
  19. 创建Rectangle类
  20. 就业率非常低!这所211大学,捅破了我国高校就业率的窗户纸……

热门文章

  1. 修改用户和用户组权限
  2. Atomic Integer 原理分析-getAndAddInt
  3. MyBatis 源码解读-loadCustomLogImpl(settings)
  4. BeanPostProcessor 源码
  5. RocketMQ消息支持的模式-消息异步发送
  6. 自己写一个实现ApplicationListener​接口并且把该组件加入到容器中
  7. 简单异常处理器SimpleMappingExceptionResolver
  8. SOA的缺陷及其与微服务的关系
  9. Filter_细节_执行流程生命周期
  10. 字符串-拆分和拼接字符串