传送门

线段树好题。

维护区间加,区间取最大值,维护区间最小值,历史区间最小值。

同样先考虑不用维护历史区间最小值的情况,这个可以参考这道题的解法,维护区间最小和次小值可以解决前两个操作,然后使用历史标记的常规维护方式合并标记更新就行了。

代码:

  1. #include<bits/stdc++.h>
  2. #define lc (p<<1)
  3. #define rc (p<<1|1)
  4. #define mid (T[p].l+T[p].r>>1)
  5. #define N 500005
  6. #define inf 2000000030
  7. using namespace std;
  8. struct Node{int l,r,sn,mn,add,his,his_add,his_mn,f;}T[N<<2];
  9. int n,m,a[N];
  10. inline int read(){
  11. int ans=0,w=1;char ch=getchar();
  12. while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
  13. while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
  14. return ans*w;
  15. }
  16. inline int min(int a,int b){return a<b?a:b;}
  17. inline void pushup(int p){
  18. T[p].his=min(T[lc].his,T[rc].his),T[lc].f=T[rc].f=0,T[p].mn=min(T[lc].mn,T[rc].mn);
  19. T[p].sn=min(T[p].mn==T[lc].mn?T[lc].sn:T[lc].mn,T[p].mn==T[rc].mn?T[rc].sn:T[rc].mn);
  20. if(T[lc].mn==T[p].mn)T[lc].f=1;
  21. if(T[rc].mn==T[p].mn)T[rc].f=1;
  22. }
  23. inline void pushadd(int p,int v){
  24. T[p].his_add=min(T[p].his_add,T[p].add+=v),T[p].sn+=v;
  25. T[p].his=min(T[p].his,T[p].mn+=v),T[p].his_mn=min(T[p].his_mn,T[p].mn);
  26. }
  27. inline void pushset(int p,int v){if(T[p].mn>=v)return;T[p].mn=v;}
  28. inline void pushdown(int p){
  29. if(T[lc].f)T[lc].his=min(T[lc].his,T[p].his_mn),T[lc].his_mn=min(T[lc].his_mn,T[p].his_mn);
  30. else T[lc].his=min(T[lc].his,T[lc].mn+T[p].his_add),T[lc].his_mn=min(T[lc].his_mn,T[lc].mn+T[p].his_add);
  31. if(T[rc].f)T[rc].his=min(T[rc].his,T[p].his_mn),T[rc].his_mn=min(T[rc].his_mn,T[p].his_mn);
  32. else T[rc].his=min(T[rc].his,T[rc].mn+T[p].his_add),T[rc].his_mn=min(T[rc].his_mn,T[rc].mn+T[p].his_add);
  33. T[lc].mn+=T[p].add,T[rc].mn+=T[p].add,T[lc].sn+=T[p].add,T[rc].sn+=T[p].add;
  34. T[lc].his_add=min(T[lc].his_add,T[lc].add+T[p].his_add);
  35. T[rc].his_add=min(T[rc].his_add,T[rc].add+T[p].his_add);
  36. T[lc].add+=T[p].add,T[rc].add+=T[p].add;
  37. if(T[lc].mn<T[p].mn)T[lc].mn=T[p].mn;
  38. if(T[rc].mn<T[p].mn)T[rc].mn=T[p].mn;
  39. T[p].add=0,T[p].his_add=0,T[p].his_mn=inf;
  40. }
  41. inline void build(int p,int l,int r){
  42. T[p].l=l,T[p].r=r,T[p].add=T[p].his_add=0,T[p].his_mn=inf;
  43. if(l==r){T[p].his=T[p].mn=a[l],T[p].sn=inf;return;}
  44. build(lc,l,mid),build(rc,mid+1,r),pushup(p);
  45. }
  46. inline void update(int p,int ql,int qr,int v){
  47. if(ql>T[p].r||qr<T[p].l)return;
  48. if(ql<=T[p].l&&T[p].r<=qr)return pushadd(p,v);
  49. pushdown(p);
  50. if(qr<=mid)update(lc,ql,qr,v);
  51. else if(ql>mid)update(rc,ql,qr,v);
  52. else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
  53. pushup(p);
  54. }
  55. inline void modify(int p,int ql,int qr,int v){
  56. if(ql>T[p].r||qr<T[p].l||T[p].mn>=v)return;
  57. if(ql<=T[p].l&&T[p].r<=qr&&T[p].sn>v)return pushset(p,v);
  58. pushdown(p);
  59. if(qr<=mid)modify(lc,ql,qr,v);
  60. else if(ql>mid)modify(rc,ql,qr,v);
  61. else modify(lc,ql,mid,v),modify(rc,mid+1,qr,v);
  62. pushup(p);
  63. }
  64. inline int query(int p,int ql,int qr,int k){
  65. if(ql>T[p].r||qr<T[p].l)return inf;
  66. if(ql<=T[p].l&&T[p].r<=qr)return k==3?T[p].mn:T[p].his;
  67. pushdown(p);
  68. if(qr<=mid)return query(lc,ql,qr,k);
  69. if(ql>mid)return query(rc,ql,qr,k);
  70. return min(query(lc,ql,mid,k),query(rc,mid+1,qr,k));
  71. }
  72. int main(){
  73. n=read(),m=read();
  74. for(register int i=1;i<=n;++i)a[i]=read();
  75. build(1,1,n);
  76. while(m--){
  77. int op=read(),l=read(),r=read();
  78. if(op==1){int v=read();update(1,l,r,v);}
  79. else if(op==2){int v=read();modify(1,l,r,v);}
  80. else printf("%d\n",query(1,l,r,op));
  81. }
  82. return 0;
  83. }

update

在做了Picks loves segment tree VIII之后学习了新的写法,然后重新写了一遍。

代码:

  1. #include<bits/stdc++.h>
  2. #define lc (p<<1)
  3. #define rc (p<<1|1)
  4. #define mid (T[p].l+T[p].r>>1)
  5. #define N 500005
  6. #define inf 2e9
  7. using namespace std;
  8. inline int read(){
  9. int ans=0,w=1;
  10. char ch=getchar();
  11. while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
  12. while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
  13. return ans*w;
  14. }
  15. struct Min{int his,mn,sn;};
  16. struct tag{int add,mnadd;};
  17. struct Node{int l,r;Min mn;tag Amin,Bmid;}T[N<<2];
  18. int n,m,a[N];
  19. inline int min(int a,int b){return a<b?a:b;}
  20. inline tag operator+(tag a,int v){return (tag){a.add+v,min(a.mnadd,a.add+v)};}
  21. inline tag operator+(tag a,tag b){return (tag){a.add+b.add,min(a.mnadd,b.mnadd+a.add)};}
  22. inline Min operator+(Min a,Min b){return (Min){min(a.his,b.his),min(a.mn,b.mn),a.mn==b.mn?min(a.sn,b.sn):(a.mn>b.mn?min(a.mn,b.sn):min(a.sn,b.mn))};}
  23. inline void pushup(int p){T[p].mn=T[lc].mn+T[rc].mn;}
  24. inline void pushadd(int p,int v){
  25. T[p].mn.his=min(T[p].mn.his,T[p].mn.mn+=v);
  26. if(T[p].mn.sn!=inf)T[p].mn.sn+=v;
  27. T[p].Amin=T[p].Amin+v,T[p].Bmid=T[p].Bmid+v;
  28. }
  29. inline void pushAmin(int p,tag v){
  30. T[p].mn.his=min(T[p].mn.his,T[p].mn.mn+v.mnadd);
  31. T[p].mn.mn+=v.add;
  32. T[p].Amin=T[p].Amin+v;
  33. }
  34. inline void pushBmid(int p,tag v){
  35. if(T[p].mn.sn!=inf)T[p].mn.sn+=v.add;
  36. T[p].Bmid=T[p].Bmid+v;
  37. }
  38. inline void pushdown(int p){
  39. int tmpmn=min(T[lc].mn.mn,T[rc].mn.mn);
  40. if(tmpmn==T[lc].mn.mn)pushAmin(lc,T[p].Amin);
  41. else pushAmin(lc,T[p].Bmid);
  42. pushBmid(lc,T[p].Bmid);
  43. if(tmpmn==T[rc].mn.mn)pushAmin(rc,T[p].Amin);
  44. else pushAmin(rc,T[p].Bmid);
  45. pushBmid(rc,T[p].Bmid);
  46. T[p].Amin=T[p].Bmid=(tag){0,0};
  47. }
  48. inline void build(int p,int l,int r){
  49. T[p].l=l,T[p].r=r,T[p].Amin=T[p].Bmid=(tag){0,0};
  50. if(l==r){T[p].mn=(Min){a[l],a[l],inf};return;}
  51. build(lc,l,mid),build(rc,mid+1,r),pushup(p);
  52. }
  53. inline void update(int p,int ql,int qr,int v){
  54. if(ql>T[p].r||qr<T[p].l)return;
  55. if(ql<=T[p].l&&T[p].r<=qr)return pushadd(p,v);
  56. pushdown(p);
  57. if(qr<=mid)update(lc,ql,qr,v);
  58. else if(ql>mid)update(rc,ql,qr,v);
  59. else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
  60. pushup(p);
  61. }
  62. inline void updmin(int p,int ql,int qr,int v){
  63. if(ql>T[p].r||qr<T[p].l||T[p].mn.mn>=v)return;
  64. if(ql<=T[p].l&&T[p].r<=qr&&T[p].mn.sn>v)return pushAmin(p,(tag){v-T[p].mn.mn,0});
  65. pushdown(p);
  66. if(qr<=mid)updmin(lc,ql,qr,v);
  67. else if(ql>mid)updmin(rc,ql,qr,v);
  68. else updmin(lc,ql,mid,v),updmin(rc,mid+1,qr,v);
  69. pushup(p);
  70. }
  71. inline int query(int p,int ql,int qr){
  72. if(ql>T[p].r||qr<T[p].l)return inf;
  73. if(ql<=T[p].l&&T[p].r<=qr)return T[p].mn.mn;
  74. pushdown(p);
  75. if(qr<=mid)return query(lc,ql,qr);
  76. if(ql>mid)return query(rc,ql,qr);
  77. return min(query(lc,ql,mid),query(rc,mid+1,qr));
  78. }
  79. inline int querymn(int p,int ql,int qr){
  80. if(ql>T[p].r||qr<T[p].l)return inf;
  81. if(ql<=T[p].l&&T[p].r<=qr)return T[p].mn.his;
  82. pushdown(p);
  83. if(qr<=mid)return querymn(lc,ql,qr);
  84. if(ql>mid)return querymn(rc,ql,qr);
  85. return min(querymn(lc,ql,mid),querymn(rc,mid+1,qr));
  86. }
  87. int main(){
  88. n=read(),m=read();
  89. for(int i=1;i<=n;++i)a[i]=read();
  90. build(1,1,n);
  91. while(m--){
  92. int op=read(),l=read(),r=read();
  93. if(op==1){int v=read();update(1,l,r,v);}
  94. if(op==2){int v=read();updmin(1,l,r,v);}
  95. if(op==3)printf("%d\n",query(1,l,r));
  96. if(op==4)printf("%d\n",querymn(1,l,r));
  97. }
  98. return 0;
  99. }

2018.07.28 uoj#169. 【UR #11】元旦老人与数列(线段树)的更多相关文章

  1. 2018.07.28 uoj#164. 【清华集训2015】V(线段树)

    传送门 线段树好题. 要求支持的操作: 1.区间变成max(xi−a,0)" role="presentation" style="position: rela ...

  2. 2018.07.29~30 uoj#170. Picks loves segment tree VIII(线段树)

    传送门 线段树好题. 维护区间取两种最值,区间加,求区间两种历史最值,区间最小值. 自己的写法调了一个晚上+一个上午+一个下午+一个晚上并没有调出来,90" role="prese ...

  3. uoj169:元旦老人与数列

    题意:http://uoj.ac/problem/169 sol  :线段树..........蜜汁TLE了一个点,不管了..... 代码抄snowMyDream的,orz........... 线段 ...

  4. ACM-ICPC 2018 南京赛区网络预赛 G Lpl and Energy-saving Lamps(线段树)

    题目链接:https://nanti.jisuanke.com/t/30996 中文题目: 在喝茶的过程中,公主,除其他外,问为什么这样一个善良可爱的龙在城堡里被监禁Lpl?龙神秘地笑了笑,回答说这是 ...

  5. UOJ.52.[UR #4]元旦激光炮(交互 思路)

    题目链接 \(Description\) 交互库中有三个排好序的,长度分别为\(n_a,n_b,n_c\)的数组\(a,b,c\).你需要求出所有元素中第\(k\)小的数.你可以调用至多\(100\) ...

  6. UOJ169. 【UR #11】元旦老人与数列

    传送门 考虑用 \(segment~tree~beats\) 那一套理论,维护区间最小值 \(mn\) 和严格次小值 \(se\) 那么可以直接 \(mlog^2n\) 维护前三个操作 考虑维护历史最 ...

  7. 【UOJ#169】元旦老人与数列

    论文题. 考虑到这题的维护和区间操作是反向的,也就是说无法像V那题快速的合并标记. 我们知道,一个区间的最小值和其他值是可以分开来维护的,因为如果一个区间被整体覆盖,那么最小值始终是最小值. 对于被覆 ...

  8. 入职第一个项目bug总结-2018/07/28

    此项目是正式入职后的第一个项目,可能各种原因重重,导致测试提出了如此多的bug,关于那些因为需求不清楚而导致的就不说了,bug总结如下: 一.ElementUI table组件出现横向滚动条 原因:因 ...

  9. 【2018.07.28】(字符串/回文串)学习Manacher算法小记

    主要是应用在回文串啦,原理也理解了老半天,如果没有图片的话,我也看不太懂它的原理 学习的灵感来源来自于:https://segmentfault.com/a/1190000008484167 /* 最 ...

随机推荐

  1. linux查看磁盘占用常用的两个命令

    1.查看总容量.已使用.未使用容量:df -hl -h:以kb以上单位显示 -l:仅显示本地文件系统 2.查看当前路径下,每个文件/夹占用空间大小:du -sh *

  2. Git .gitignore使用 -- 过滤class文件或指定目录

    1. 进入当前的项目根目录 执行 git init touch .gitignore 2. 过滤class文件或指定目录 *.class /target/ 3. 提交 git add . 将所有文件提 ...

  3. AS3 巧用事件api简化鼠标拖动流程

     拖动,按照一般人的定义,拖动就是鼠标按下的时候移动鼠标,这里面有三个过程,分别是按下.移动鼠标和弹起.以stage为例,大家的实现步骤通常如下:(PS:此处不讨论startDrag和stopDrag ...

  4. android -chrome 调试

    在chrome上 输入 chrome://inspect/ 连接手机,配置 监听8000,和8080端口 cordova默认是8000端口 如果出现白屏:原因:google在首次加载时,要进行服务器连 ...

  5. Java 跨域 CrossOrigin注解 Filter拦截 Nginx配置

    说明 资源请求的发起方与请求的资源不在同一个域中的: 一般的,只要网站的[协议名protocol].[主机host].[端口号port]这三个中的任意一个不同,网站间的数据请求与传输便构成了跨域调用: ...

  6. 八月(The Summer is Gone)观后感

    第一次看到这部电影时觉得很亲近,黑白画面,国企改革的背景,浓浓的儿时画面感,原谅我只是一个三十不到的人,可能我比较早熟,对八九十年代还有些记忆,更早以前也通过电视.音乐.书籍等了解过一些,而那些听过又 ...

  7. python中if __name__ == '__main__': 解析

    当你打开一个.py文件时,经常会在代码的最下面看到if __name__ ==  '__main__':,现在就来介 绍一下它的作用. 模块是对象,并且所有的模块都有一个内置属性 __name__.一 ...

  8. scala spark 调用hivecontext

    import org.apache.spark.rdd.RDD def save(data: RDD[ModelReplay], modelKey: String, dt: String): Unit ...

  9. Mysql update 索引

    执行mysql update,或者delete的时候会遇到: You can't specify target table for update in FROM clause 相关的原因自不必说:下面 ...

  10. ubuntu中vim的设置

    问题:刚安装的VIM中,backspace不能删除字符,且上下左右箭头没反应. 解决方法: sudo vi  /etc/vim/vimrc.tiny 修改 set compatible为set noc ...