CF526F Pudding Monsters

  • problem
  • solution
  • code

problem

luogu翻译

solution

observation每行每列恰好有一个棋子,所以如果一段区间 [l,r][l,r][l,r] 会被某个 kkk 统计,当且仅当这个区间内棋子纵坐标 ymax−ymin+1=r−l+1y_{max}-y_{min}+1=r-l+1ymax​−ymin​+1=r−l+1。

发现这是经典的连续段计数问题

标配:单调栈 +++ 线段树。

将所有棋子按照横坐标升序排序。

枚举右端点 rrr,线段树上每个叶子节点 lll 维护的是 [l,r][l,r][l,r] 的信息。

转换一下条件判定:ymax−ymin+l−r=0y_{max}-y_{min}+l-r=0ymax​−ymin​+l−r=0。

因为每行每列恰好一个棋子,所以所有情况都有 ymax−ymin≥r−ly_{max}-y_{min}\ge r-lymax​−ymin​≥r−l。

而最后要计入答案的是取等的情况,即最小值。

所以线段树就维护 ymax−ymin+l−ry_{max}-y_{min}+l-rymax​−ymin​+l−r 的最小值,以及最小值个数。

最后统计的时候,就统计最小值为 000 的节点信息。

  • rrr 每次都是 +1+1+1,对应的是线段树整体 −1-1−1。

  • lll 与 rrr 无关,在最开始建树是加上即可。

  • ymaxy_{max}ymax​,维护一个单增栈,栈中第 toptoptop 个元素维护的是区间 [sMax[top−1]+1,sMax[top]]\Big[sMax[top-1]+1,sMax[top]\Big][sMax[top−1]+1,sMax[top]] 的最大值信息,即这一段的纵坐标最大值都是 sMax[top]sMax[top]sMax[top]。

    每次用右端点 rrr 与栈比较纵坐标大小,如果 rrr 大则弹栈,将 toptoptop 维护的区间加上 yr−ysMax[top]y_r-y_{sMax[top]}yr​−ysMax[top]​。

  • yminy_{min}ymin​,维护一个单减栈,栈中第 toptoptop 个元素维护的是区间 [sMin[top−1]+1,sMin[top]]\Big[sMin[top-1]+1,sMin[top]\Big][sMin[top−1]+1,sMin[top]] 的最大值信息,即这一段的纵坐标最小值都是 sMin[top]sMin[top]sMin[top]。

    每次用右端点 rrr 与栈比较纵坐标大小,如果 rrr 小则弹栈,将 toptoptop 维护的区间加上 ysMin[top]−yiy_{sMin[top]-y_i}ysMin[top]−yi​​。

事件复杂度为 O(nlog⁡n)O(n\log n)O(nlogn)。

code

#include <bits/stdc++.h>
using namespace std;
#define maxn 300005
int n, tMax, tMin;
int x[maxn], y[maxn], id[maxn], sMax[maxn], sMin[maxn];
struct node { int tag, Min, cnt; }t[maxn << 2];#define lson now << 1
#define rson now << 1 | 1
#define mid ( ( l + r ) >> 1 )void pushup( int now ) {if( t[lson].Min < t[rson].Min ) t[now].Min = t[lson].Min, t[now].cnt = t[lson].cnt;else if( t[lson].Min > t[rson].Min ) t[now].Min = t[rson].Min, t[now].cnt = t[rson].cnt;else t[now].Min = t[lson].Min, t[now].cnt = t[lson].cnt + t[rson].cnt;
}void pushdown( int now ) {if( t[now].tag ) {t[lson].tag += t[now].tag;t[rson].tag += t[now].tag;t[lson].Min += t[now].tag;t[rson].Min += t[now].tag;t[now].tag = 0;return;}
}void build( int now, int l, int r ) {if( l == r ) { t[now].Min = l, t[now].cnt = 1; return; }build( lson, l, mid );build( rson, mid + 1, r );pushup( now );
}void modify( int now, int l, int r, int L, int R, int k ) {if( R < l or r < L ) return;if( L <= l and r <= R ) { t[now].Min += k, t[now].tag += k; return; }pushdown( now );modify( lson, l, mid, L, R, k );modify( rson, mid + 1, r, L, R, k );pushup( now );
}int query( int now, int l, int r, int L, int R ) { if( R < l or r < L ) return 0;if( L <= l and r <= R ) return t[now].Min ? 0 : t[now].cnt;return query( lson, l, mid, L, R ) + query( rson, mid + 1, r, L, R );
}int main() {scanf( "%d", &n );for( int i = 1;i <= n;i ++ ) scanf( "%d %d", &x[i], &y[i] ), id[i] = i;sort( id + 1, id + n + 1, []( int u, int v ) { return x[u] < x[v]; } );build( 1, 1, n );long long ans = 0;for( int i = 1;i <= n;i ++ ) {modify( 1, 1, n, 1, n, -1 );modify( 1, 1, n, x[sMax[tMax]] + 1, i, y[id[i]] );modify( 1, 1, n, x[sMin[tMin]] + 1, i, -y[id[i]] );while( tMax and y[sMax[tMax]] < y[id[i]] ) {modify( 1, 1, n, x[sMax[tMax - 1]] + 1, x[sMax[tMax]], y[id[i]] - y[sMax[tMax]] );tMax --;}while( tMin and y[sMin[tMin]] > y[id[i]] ) {modify( 1, 1, n, x[sMin[tMin - 1]] + 1, x[sMin[tMin]], y[sMin[tMin]] - y[id[i]] );tMin --;}sMax[++ tMax] = sMin[++ tMin] = id[i];ans += query( 1, 1, n, 1, i );}printf( "%lld\n", ans );return 0;
}

[CF 526 F] Pudding Monsters(单调栈 + 线段树)相关推荐

  1. HDU - 6989 Didn‘t I Say to Make My Abilities Average in the Next Life?! 莫队/单调栈 + 线段树/ST表在线

    传送门 文章目录 题意: 思路: 题意: 思路: 考虑将贡献分开来算,先计算最大值,再算个最小值,之后答案就是((max+min)/2)/(len∗(len+1)/2)((max+min)/2)/(l ...

  2. COCI 2015/2016 PROKLETNIK(单调栈+线段树)

    COCI 2015/2016 PROKLETNIK 题目大意 给定序列A1..NA_{1..N}A1..N​,分别求出QQQ组询问区间[L,R][L,R][L,R]中最长的连续子序列Al..rA_{l ...

  3. 2019南昌网络赛-I(单调栈+线段树)

    题目链接:https://nanti.jisuanke.com/t/38228 题意:定义一段区间的值为该区间的和×该区间的最小值,求给定数组的最大的区间值. 思路:比赛时还不会线段树,和队友在这题上 ...

  4. [LOJ3153] 三级跳(单调栈 + 线段树)

    problem loj3153 solution 有一个显然正确但又不起眼却是正解必备的结论: 考虑 (x,y,z)(x,y,z)(x,y,z) 答案三元对,如果有一个数 i∈(x,y)∧ai≥axi ...

  5. 扶桑号战列舰 (单调栈+线段树区间更新懒惰标记 or 栈)

    传送门 •题目描述 题目描述 众所周知,一战过后,在世界列强建造超无畏级战列舰的竞争之中,旧日本海军根据"个舰优越主义",建造了扶桑级战列舰,完工时为当时世界上武装最为强大的舰只. ...

  6. [单调栈+线段树] 2020-2021 ICPC, NERC, Southern and Volga Russian Regional Contest ——A. LaIS

    题面$ link   定义了长度为 kkk 的几乎递增序列 {bi}\{b_i\}{bi​} 为: min(b1,b2)≤min(b2,b3)≤...min(bk−1,bk)min(b_1, b_2) ...

  7. L. Continuous Intervals(单调栈 + 线段树 + 思维)

    L. Continuous Intervals 给定一个长度为nnn的数组,问里面有多少个区间[l,r][l, r][l,r],满足,对这个区间排序后,两两差值$ \leq 1$,输出区间个数. 如果 ...

  8. 【BZOJ4262】Sum 单调栈+线段树

    [BZOJ4262]Sum Description Input 第一行一个数 t,表示询问组数. 第一行一个数 t,表示询问组数. 接下来 t 行,每行四个数 l_1, r_1, l_2, r_2. ...

  9. 扶桑号战列舰【单调栈+线段树】

    扶桑号战列舰 传送门  来源upc:12800 题目描述 众所周知,一战过后,在世界列强建造超无畏级战列舰的竞争之中,旧日本海军根据"个舰优越主义",建造了扶桑级战列舰,完工时为当 ...

最新文章

  1. C# Revert 单词反转字符串!『测试通过』
  2. LINE: Large-scale Information Network Embedding
  3. Qt for Android获取手机序列号/手机型号/手机制造商
  4. 判断ABAP software component是否可修改及可extend的API
  5. Linux命令之目录和文件操作
  6. Python学习指南高清PDF版,速存!24小时后删除
  7. div自动滚动_简易数据分析 10 | Web Scraper 翻页——抓取「滚动加载」类型网页
  8. 爆料喽!!!开源日志库Logger的剖析分析
  9. python mmap_python标准库基础之mmap:内存映射文件
  10. linux 压缩文件 zip,linux zip命令压缩zip文件详解
  11. windows命令修改IP地址
  12. 从零开始制作PPT(母版设计,素材填充,配色等)
  13. 一文汇总卡方检验分析步骤
  14. python基础篇{数据类型}
  15. java freemarker word导出 文字加图片双重循环 (经历无数坑)
  16. 教你修改电脑mac地址图解教程
  17. VUE 自定义子组件v-bind及v-on指令的大小写问题
  18. 中国大数据行业人才生态现状
  19. 计算机故障检修的常用流程及方法,常见品牌变频空调通讯故障通用检修流程与方法...
  20. 让甲方爸爸看PDF格式的图纸,该测量长度?

热门文章

  1. java里面什么时候环境变量_Java的环境变量什么时候需要设置?
  2. mysql 免费前端_MySQL
  3. 云管边端架构图_中移物联网布局构建“云-管-端”全方位体系架构
  4. pythonopencv显示图像_OpenCV-Python 读取显示图像 | 五
  5. python tkinter进度条_在python3.7中更新tkinter进度条
  6. startindex 不能大于字符串长度_玩转云端丨redis的5种对象与8种数据结构之字符串对象(下)...
  7. lol修改服务器域名,LOL历史转区用户解冻大区官网自助系统地址 新版申请解冻账号网址...
  8. Java 泛型 泛型的约束与局限性
  9. java pojo 是什么_什么是POJO
  10. 读数据库遇到空就进行不下去_如何保证缓存与数据库的双写一致性?