题目描述

给定一个长度为 nn且初始值全为 00的序列。你需要支持以下两种操作:

  • Add L, R, hL,R,h:将序列 [L, R][L,R]内所有值小于 hh的元素都赋为 hh,此时不改变高度大于 hh的元素值
  • Remove L, R, hL,R,h:将序列 [L, R][L,R]内所有值大于 hh的元素都赋为 hh,此时不改变高度小于 hh的元素值

你需要输出进行 kk次上述操作之后的序列。

解析

显然每次操作会对一段区间的取值范围造成影响,那么不妨我们维护区间取值的上下界,就可以轻松A掉这题。

最简单的方法就是线段树(不过貌似有人高级数据结构T了233)

那么维护上下界实质上也就是维护区间最大最小值,所以我们每次打个lazytag以保留操作对区间的影响就行了。注意是打标记而不是维护信息,我们不用区间查询,维护了这堆信息也没用,还浪费时间。。。

最后输出我们把lazytag造成的所有影响很好的维护出来,再遍历一次整棵线段树输出叶子节点的lazytag就行了。

那如何维护lazytag呢?我们就要关注pushdown怎么弄。

设\(up(h),down(h)\)分别对应在线段树上进行Add,Remove两种操作,改变的高度为\(h\)。

对于\(up(h)\),设改变的区间上下界为\(u,d\):

  1. 若\(x<d\),不会对区间造成影响
  2. 若\(d<x<u\),此时\(d\)变为\(x\),\(u\)不变
  3. 若\(x>u\),此时\(d,u\)都变为\(x\)。

参考代码

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cmath>
  4. #include<cstring>
  5. #include<ctime>
  6. #include<cstdlib>
  7. #include<algorithm>
  8. #include<queue>
  9. #include<set>
  10. #include<map>
  11. #define INF 0x3f3f3f3f
  12. #define N 2000010
  13. using namespace std;
  14. inline int read()
  15. {
  16. int f=1,x=0;char c=getchar();
  17. while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
  18. while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
  19. return x*f;
  20. }
  21. struct node{
  22. int l,r;
  23. int up,down;
  24. }t[N<<2];
  25. int n,k;
  26. inline void pushdown(int p)
  27. {
  28. if(p==0) return;
  29. if(t[p].up!=0){
  30. t[p<<1].up=max(t[p].up,t[p<<1].up);
  31. t[p<<1|1].up=max(t[p].up,t[p<<1|1].up);
  32. if(t[p<<1].down<t[p].up) t[p<<1].down=t[p].up;
  33. if(t[p<<1|1].down<t[p].up) t[p<<1|1].down=t[p].up;
  34. t[p].up=0;
  35. }
  36. if(t[p].down!=INF){
  37. t[p<<1].down=min(t[p].down,t[p<<1].down);
  38. t[p<<1|1].down=min(t[p].down,t[p<<1|1].down);
  39. if(t[p<<1].up>t[p].down) t[p<<1].up=t[p].down;
  40. if(t[p<<1|1].up>t[p].down) t[p<<1|1].up=t[p].down;
  41. t[p].down=INF;
  42. }
  43. }
  44. inline void build(int p,int l,int r)
  45. {
  46. t[p].l=l,t[p].r=r;t[p].up=0,t[p].down=INF;
  47. if(l==r) return;
  48. int mid=(l+r)>>1;
  49. build(p<<1,l,mid);
  50. build(p<<1|1,mid+1,r);
  51. }
  52. inline void up(int p,int l,int r,int val)
  53. {
  54. if(l<=t[p].l&&t[p].r<=r){
  55. t[p].up=max(t[p].up,val);
  56. t[p].down=max(val,t[p].down);
  57. return;
  58. }
  59. pushdown(p);
  60. int mid=(t[p].l+t[p].r)>>1;
  61. if(l<=mid) up(p<<1,l,r,val);
  62. if(r>mid) up(p<<1|1,l,r,val);
  63. }
  64. inline void down(int p,int l,int r,int val)
  65. {
  66. if(l<=t[p].l&&t[p].r<=r){
  67. t[p].down=min(t[p].down,val);
  68. t[p].up=min(t[p].up,val);
  69. return;
  70. }
  71. pushdown(p);
  72. int mid=(t[p].l+t[p].r)>>1;
  73. if(l<=mid) down(p<<1,l,r,val);
  74. if(r>mid) down(p<<1|1,l,r,val);
  75. }
  76. inline void query(int p,int l,int r)
  77. {
  78. if(t[p].l==t[p].r){
  79. printf("%d\n",t[p].up);
  80. return;
  81. }
  82. pushdown(p);
  83. int mid=(t[p].l+t[p].r)>>1;
  84. if(l<=mid) query(p<<1,l,r);
  85. if(r>mid) query(p<<1|1,l,r);
  86. }
  87. int main()
  88. {
  89. n=read(),k=read();
  90. build(1,1,n);
  91. for(int i=1;i<=k;++i){
  92. int cmd=read(),l=read(),r=read(),val=read();
  93. ++l,++r;
  94. if(cmd==1) up(1,l,r,val);
  95. else down(1,l,r,val);
  96. }
  97. query(1,1,n);
  98. return 0;
  99. }

P4560 [IOI2014]Wall 砖墙的更多相关文章

  1. LUOGU P4560 [IOI2014]Wall 砖墙 (线段树)

    传送门 解题思路 线段树打标记,刚开始想复杂了,维护了四个标记.后来才知道只需要维护一个最大值最小值即可,然后更新的时候分类讨论一下. 代码 #include<iostream> #inc ...

  2. 4364: [IOI2014]wall砖墙

    4364: [IOI2014]wall砖墙 链接 分析: 线段树,维护一个最大值,一个最小值. 代码: #include<bits/stdc++.h> ],*p1 = buf,*p2 = ...

  3. bzoj4364: [IOI2014]wall砖墙

    线段树打标记的好(luo)题 打打标记,记得下移 = =听说2000000是用来卡线段树的 = =怎么办呢,,, = =打个读入优化看看能不能卡过去吧 #include<cstdio> # ...

  4. BZOJ4364: [IOI2014]wall砖墙(线段树)

    题意 题目链接 Sol 一个显然的思路是维护最大最小值以及最大最小值的覆盖标记. https://paste.ubuntu.com/p/WXpBvzF6Y2/ 但实际上因为这题只需要输出最后的操作序列 ...

  5. 【[IOI2014]Wall 砖墙】

    好像随便一卡就最优解了 malao告诉我这道题挺不错的,于是就去写了写 这两个操作很有灵性啊,感觉这么有特点的数大概是需要分块维护的吧 但是并没有什么区间查询,只是在最后输出整个序列 于是我们就直接用 ...

  6. [IOI2014]Wall

    [IOI2014]Wall 题目大意: 给你一个长度为\(n(n\le2\times10^6)\)的数列,初始全为\(0\).\(m(m\le5\times10^5)\)次操作,每次让区间\([l_i ...

  7. 「IOI2014」Wall 砖墙

    题目描述 给定一个初始元素为 \(0\) 的数列,以及 \(K\) 次操作: 将区间 \([L, R]\) 中的元素对 \(h\) 取 \(max\) 将区间 \([L, R]\) 中的元素对 \(h ...

  8. BZOJ4364:[IOI2014]Wall

    浅谈区间最值操作与历史最值问题:https://www.cnblogs.com/AKMer/p/10225100.html 题目传送门:https://lydsy.com/JudgeOnline/pr ...

  9. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

随机推荐

  1. 【转载】嵌入式 Linux 移植 Dropbear SSH server

    0. 背景  OpenSSH因为其相对较大,一般不太适用于嵌入式平台,多用于PC或者服务器的Linux版本中.  Dropbear是一个相对较小的SSH服务器和客户端.它运行在一个基于POSIX的各种 ...

  2. JSON学习(三)

    案例: * 校验注册用户名是否存在 在注册页面,填写完用户名且该栏失去焦点时,前端会进行ajax传输该内容与后台数据库进行比对, 若数据库中没有该用户名,则用户栏后显示“用户名可用”,反之,则显示&q ...

  3. AtCoder-abc147 (题解)

    A - Blackjack (水题) 题目链接 大致思路: 水题 B - Palindrome-philia (水题) 题目链接 大致思路: 由于整个串是回文串,只要判断前一半和后一半有多少个不同即可 ...

  4. MySQL表关系--外键

    一.外键前戏 如果我们把所有的信息都记录在一张表中会带来的问题: 1.表的结构不清晰 2.浪费磁盘空间 3.表的扩展性极差 所以我们要把这种表拆成几张不同的表,分析表与表之间的关系. 确定表与表之间的 ...

  5. flask db操作

    from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) # app.config[' ...

  6. SonarQube安装教程与简单使用(基于Centos7,JDK1.8)

    SonarQube 若要转载本文,请务必声明出处:https://www.cnblogs.com/zhongyuanzhao000/p/11686522.html 概念: SonarQube是一种自动 ...

  7. C#高效编程

    一. 使用readonly而不是const const是编译时常量,readonly是运行时常量.如果引用了一个库中的const常量,则在更新了程序集,但应用程序没有重新编译时,运行结果会出错 如程序 ...

  8. kubernetes使用securityContext和sysctl

    前言 在运行一个容器时,有时候需要使用sysctl修改内核参数,比如net..vm..kernel等,sysctl需要容器拥有超级权限,容器启动时加上--privileged参数即可.那么,在kube ...

  9. tf.reduce_mean函数用法及有趣区别

    sess=tf.Session() a=np.array([1,2,3,5.]) # 此代码保留为浮点数 a1=np.array([1,2,3,5]) # 此代码保留为整数 c=tf.reduce_m ...

  10. 《区块链DAPP开发入门、代码实现、场景应用》笔记1——天外飞仙DAPP

    Solidity编程语言解决了编写智能合约的不友好的问题,但是当合约编译并部署之后,对与这些接口的访问,对于一般的使用者来说,门槛有点高, 对普通用户来说也是非常不友好,为了使广大用户理解并方便快捷的 ...