Pudding Monster

题目连接:https://www.luogu.org/problem/show?pid=CF526F

问题提出

  • 给长度为nnn的排列AAA.
  • 问有多少(l,r)(l,r)(l,r),使得将Al,Al+1,...,ArA_l,A_{l+1},...,A_rAl​,Al+1​,...,Ar​排序之后是连续的一段数.
  • n≤105n \le 10^5n≤105

问题解决

判断一段区间是否能连续,只要判断是否满足max−min=r−lmax-min=r-lmax−min=r−l即可.

也即判断区间是否满足max−min+l=rmax-min+l = rmax−min+l=r.

先天有max−min+l≥rmax-min+l \ge rmax−min+l≥r

因此我们可以考虑枚举区间端点rrr,然后使用线段树维护左边所有区间(每个区间用左端点唯一标识)的l+max−minl+max-minl+max−min的值.

我们还需要线段树满足求线段内最小值是谁,最小值有多少个的功能.

考虑到区间右端点向右移动的过程中,原有的区间再加上rrr形成的新区间的maxmaxmax不会变小,minminmin值不会变大.

而maxmaxmax变大也会是一批区间一起增大,增量也是相同的,因此可以转化为区间修改操作.

我们可以用222个单调栈来维护当前的最大值序列,和最小值序列.

每次将rrr点加入左边所有的区间,从而形成新的区间,根据单调栈保存的信息,确定出哪些区间的最大值或者是最小值需要被修改,然后进行区间修改.

询问时候,直接查询[1,r][1,r][1,r]内最小值为000的个数,算贡献.

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#define pr(x) std::cout << #x << ':' << x << std::endl
#define rep(i,a,b) for(int i = a;i <= b;++i)
#define clr(x) memset(x,0,sizeof(x))
#define setinf(x) memset(x,0x3f,sizeof(x))const int N = 300007,inf = 1e9;
int n,m;
typedef std::pair<int,int> pii;
int a[N];struct node{int val,cnt,tag,len;node(int val = 0,int cnt = 1,int tag = 0,int len = 1):val(val),cnt(cnt),tag(tag),len(len){}
}ns[N<<2];
//线段树维护的是区间最小值以及最小值的个数
inline void pushdown(int o) {if(ns[o].tag) {ns[o<<1].val += ns[o].tag;ns[o<<1|1].val += ns[o].tag;ns[o<<1].tag += ns[o].tag;ns[o<<1|1].tag += ns[o].tag;ns[o].tag = 0;}
}inline node maintain(node &lch,node &rch) {node res = node(std::min(lch.val,rch.val),0,0,lch.len+rch.len);if(lch.val == res.val) res.cnt += lch.cnt;if(rch.val == res.val) res.cnt += rch.cnt;return res;
}inline void change(int o,int l,int r,int cl,int cr,int val) {if(cl <= l && r <= cr) {ns[o].tag += val;ns[o].val += val;return ;}   if(r < cl || cr < l) return;int mid = (l + r) >> 1;pushdown(o);change(o<<1,l,mid,cl,cr,val);change(o<<1|1,mid+1,r,cl,cr,val);ns[o] = maintain(ns[o<<1],ns[o<<1|1]);
}inline node query(int o,int l,int r,int ql,int qr) {if(ql <= l && r <= qr) return ns[o];if(r < ql || qr < l)return node(inf,1,0,0);int mid = (l + r) >> 1;pushdown(o);node lch = query(o<<1,l,mid,ql,qr);node rch = query(o<<1|1,mid+1,r,ql,qr);return maintain(lch,rch);
}inline void build(int o,int l,int r) {if(l == r) {ns[o] = node(0,1,0,1);return ;}int mid = (l + r) >> 1;build(o<<1,l,mid);build(o<<1|1,mid+1,r);ns[o] = maintain(ns[o<<1],ns[o<<1|1]);
}pii mx[N],mi[N];
int topx,topi;int main() {std::cin >> n;build(1,1,n);rep(i,1,n) {int idx,y;std::cin >> idx >> y;a[idx] = y;}long long ans = 0;rep(i,1,n) {change(1,1,n,i,i,i);while(topx > 0 && mx[topx].first < a[i]) {change(1,1,n,mx[topx-1].second+1,mx[topx].second,a[i] - mx[topx].first);topx--;}mx[++topx] = (pii){a[i],i};while(topi > 0 && mi[topi].first > a[i]) {change(1,1,n,mi[topi-1].second+1,mi[topi].second,mi[topi].first - a[i]);topi--;}mi[++topi] = (pii){a[i],i};change(1,1,n,1,i,-i);node res = query(1,1,n,1,i);ans += res.cnt;change(1,1,n,1,i,i);}std::cout << ans << std::endl;return 0;
}

线段树-Pudding Monster CF526F-单调栈相关推荐

  1. [CF 526 F] Pudding Monsters(单调栈 + 线段树)

    CF526F Pudding Monsters problem solution code problem luogu翻译 solution observation :每行每列恰好有一个棋子,所以如果 ...

  2. 线段树、优先队列、单调队列小结

    原文转自:http://blog.csdn.net/lhshaoren/article/details/7897736 主要处理问题: 线段树:区间处理,一般需要对整个区间执行相同的操作,时间复杂度O ...

  3. HDU 4942 Game on S♂play(线段树、模拟、扩栈)

    比赛的时候想到这题的大概做法,但由于卡别的水题...就赛后做了... 题意:给一个二叉树,每个结点有一个w[i],有3种操作,0 x表示左旋x,1 x表示右旋x,3 x表示询问x结点的价值,其中,价值 ...

  4. [BZOJ 2957]楼房重建(THU2013集训)(线段树维护单调栈)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2957 分析: 根据题意,就是比较斜率大小 只看一段区间的话,那么这段区间能看见的楼房数量就是这 ...

  5. UOJ#7. 【NOI2014】购票 | 线段树 凸包优化DP

    题目链接 UOJ #7 题解 首先这一定是DP!可以写出: \[f[i] = \min_{ancestor\ j} \{f[j] + (d[j] - d[i]) * p[i] + q[i]\}\] 其 ...

  6. LOJ 121 「离线可过」动态图连通性——LCT维护删除时间最大生成树 / 线段树分治...

    题目:https://loj.ac/problem/121 离线,LCT维护删除时间最大生成树即可.注意没有被删的边的删除时间是 m+1 . 回收删掉的边的节点的话,空间就可以只开 n*2 了. #i ...

  7. CodeForces - 817D Imbalanced Array(单调栈)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的序列,求出所有子区间的最大值与最小值之差的和 题目分析:不难看出最大值和最小值之差的和可以拆开,拆成最大值之和与最小值之和之差,现在问题转换为如 ...

  8. LibreOJ - 3083 与或和(单调栈+位运算)

    题目链接:点击查看 题目大意:给出一个 n∗mn*mn∗m 的矩阵,求所有子矩阵的"按位与和"和"按位或和" 题目分析:通过样例一的提示,不难想到拆位之后原矩阵 ...

  9. bzoj2286 [Sdoi2011]消耗战 单调栈+lca

    这个题意思非常明确,就是删除尽量小的边使1和指定点不连通 对于一次询问,dfs一遍即可,但需要log级别的 然后条件里有个Σ,显然复杂度和他有关,对每个点都需要一个均摊log的 然后有两个基本思路, ...

最新文章

  1. html带颜色表格怎么做,使用HTML添加表格4(行颜色与表格嵌套)——零基础自学网页制作...
  2. GitLab-使用SSH的方式拉取和推送项目
  3. Boost:等待和通知操作的模糊测试
  4. 华为上机试题:最高分是多少
  5. C语言--在终端输入多行信息,找出包含“ould”的行,并打印改行
  6. 一张正方形图片,伴随我一年半,敢问情绪的使用方法
  7. 关于mysql中GROUP_CONCAT函数的使用
  8. 算法竞赛入门经典 第七章 总结
  9. 存储桶列表访问权限_十分钟从入门到精通(上)——OBS权限配置
  10. [文章存档]Azure上部署的java app在向第三方服务传送中文时出现乱码
  11. 中兴通讯:将在全球范围内发布近10款5G手机
  12. 小米装android4.4,在VM已安装Android4.4 连接小米手环 网络设置
  13. 爆炸的符卡洋洋洒洒(01背包)
  14. sqlite3:not found 解决方法
  15. 简单PHP留言板之二 —— PHP的数据库连接文件
  16. Lingo 实现线性规划求解模型
  17. Redis势不可挡系列之概念剖析
  18. ES6: 模板字符串
  19. 罗格斯的计算机科学博士奖学金,罗格斯大学cs
  20. 计算机视觉方向简介 | 驾驶员监控DMS

热门文章

  1. 算法设计与分析——贪心算法——多机调度问题
  2. 7-48 银行排队问题之单窗口“夹塞”版 (30 分)(思路和详解+map做法)来呀Baby!
  3. 高等数学下-赵立军-北京大学出版社-题解-练习11.3
  4. List(C++模版实现的带哨兵的双向链表)
  5. mysql数据剪切到新表_6、MySQL核心DDL语句
  6. 里加一列为1_9月1号新宠物食品法规实施啦,辣鸡宠物食品遭殃,你也可能违法...
  7. H.266 参考软件VTM下载和安装
  8. spyder 护眼背景
  9. GPU Shader 程序调试方法
  10. HDU 6428 Problem C. Calculate(积性函数)