• 题目链接:

    https://www.luogu.org/problemnew/show/UVA11992

  • 题目大意:

    一个r*c的矩阵,一开始元素都是0,然后给你m次三种操作,分别是将一个子矩阵中所有元素加上v,将一个子矩阵元素全部修改成v,询问一个子矩阵中所有元素和,最大值和最小值.

  • 思路:

    应该说是一道有点毒瘤的数据结构题(然而时限居然给了5s)了,虽然它的主体只是线段树。我们可以把每一行都看作一棵线段树,这样操作就十分方便了。

    然后就是修改值的操作,对于初学者可能有点棘手,但实际上并不难,我们同样可以用lazy_tag打标记。但是就有一些要注意的东西了,当我们打add(元素加值)标记时是不会影响set(修改值)标记的,但是我们在打set标记时无论你前面add标记是多少,此时就相当于作废,所以直接将add标记赋为0就好了,然后直接修改sum,mi和mx(分别记录该区间的和,最小值,最大值)。

    同时我们可以让query询问函数直接返回一个存了sum,mi,mx的结构体,这样就不用查三次了.

    同时还有一个去要注意的地方,正如我们前面分析的那样,每一行开一颗线段树,但是实际上你真的不能搞一个tree[maxn],然后每一个tree中存一个线段树的结构体,这样是绝壁会爆的(我一开始就这么搞),而是和平常一样搞一个存全部元素的数组,具体怎么做还请看代码,我自认为还是写的比较直观。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <algorithm>
  6. #include <cctype>
  7. #include <vector>
  8. using namespace std;
  9. const int maxn=1000005;
  10. const int inf=0xfffffff;
  11. int r,c,m,v;
  12. int L,R;
  13. struct Tmp{
  14. Tmp() : sum(0), mx(-inf),mi(inf) {}//构造函数,非常方便,强烈推荐
  15. Tmp(int x,int y,int z) :sum(x),mx(y),mi(z) {}
  16. int sum;
  17. int mx,mi;
  18. };//query询问时直接返回这个结构体就好了
  19. int sum[maxn<<2],add[maxn<<2],set[maxn<<2],mx[maxn<<2],mi[maxn<<2];
  20. inline void up(int now){
  21. sum[now]=sum[now<<1]+sum[now<<1|1];
  22. mx[now]=max(mx[now<<1],mx[now<<1|1]);
  23. mi[now]=min(mi[now<<1],mi[now<<1|1]);
  24. return ;
  25. }
  26. void build(int now,int l,int r){//其实build一点用也没有,请大家忽略
  27. if(l==r){
  28. mx[now]=0;//-inf;
  29. mi[now]=0;//inf;
  30. return ;
  31. }
  32. int mid=(l+r)>>1;
  33. build(now<<1,l,mid);
  34. build(now<<1|1,mid+1,r);
  35. up(now);
  36. return ;
  37. }
  38. inline void down(int now,int ln,int rn){//注意看这个push_down函数
  39. if(set[now]){//修改标记
  40. sum[now<<1]=set[now]*ln;
  41. sum[now<<1|1]=set[now]*rn;
  42. set[now<<1]=set[now];
  43. set[now<<1|1]=set[now];
  44. add[now<<1]=add[now<<1|1]=0;
  45. mx[now<<1]=mx[now<<1|1]=set[now];
  46. mi[now<<1]=mi[now<<1|1]=set[now];
  47. set[now]=0;
  48. }
  49. if(add[now]){//加值标记
  50. sum[now<<1]+=add[now]*ln;
  51. sum[now<<1|1]+=add[now]*rn;
  52. add[now<<1]+=add[now];
  53. add[now<<1|1]+=add[now];
  54. mx[now<<1]+=add[now];
  55. mi[now<<1]+=add[now];
  56. mx[now<<1|1]+=add[now];
  57. mi[now<<1|1]+=add[now];
  58. add[now]=0;
  59. }
  60. return ;
  61. }
  62. void update_add(int now,int l,int r){
  63. if(L<=l&&r<=R){
  64. add[now]+=v;
  65. sum[now]+=v*(r-l+1);
  66. mx[now]+=v;
  67. mi[now]+=v;
  68. return ;
  69. }
  70. int mid=(l+r)>>1;
  71. down(now,mid-l+1,r-mid);
  72. if(L<=mid)update_add(now<<1,l,mid);
  73. if(mid<R)update_add(now<<1|1,mid+1,r);
  74. up(now);
  75. return ;
  76. }
  77. void update_set(int now,int l,int r){
  78. if(L<=l&&r<=R){
  79. set[now]=v;
  80. sum[now]=v*(r-l+1);
  81. add[now]=0;
  82. mx[now]=v;
  83. mi[now]=v;
  84. return ;
  85. }
  86. int mid=(l+r)>>1;
  87. down(now,mid-l+1,r-mid);
  88. if(L<=mid)update_set(now<<1,l,mid);
  89. if(mid<R)update_set(now<<1|1,mid+1,r);
  90. up(now);
  91. return ;
  92. }
  93. Tmp query(int now,int l,int r){
  94. if(L<=l&&r<=R){
  95. return Tmp(sum[now],mx[now],mi[now]);//十分方便
  96. }
  97. int mid=(l+r)>>1;
  98. down(now,mid-l+1,r-mid);
  99. Tmp tmp;
  100. int sum=0,mx=-inf,mi=inf;
  101. if(L<=mid){
  102. tmp=query(now<<1,l,mid);
  103. sum+=tmp.sum;
  104. mx=max(mx,tmp.mx);
  105. mi=min(mi,tmp.mi);
  106. }
  107. if(mid<R){
  108. tmp=query(now<<1|1,mid+1,r);
  109. sum+=tmp.sum;
  110. mx=max(mx,tmp.mx);
  111. mi=min(mi,tmp.mi);
  112. }
  113. // up(now); //然而并不用up()
  114. tmp.sum=sum,tmp.mi=mi,tmp.mx=mx;
  115. return tmp;
  116. }
  117. template <class T>inline void read(T &x){
  118. x=0;int ne=0;char c;
  119. while(!isdigit(c=getchar()))ne=c=='-';
  120. x=c-48;
  121. while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
  122. x=ne?-x:x;
  123. return ;
  124. }
  125. int main()
  126. {
  127. int op,x1,x2,y1,y2;
  128. read(r),read(c),read(m);
  129. // build(1,1,r*c);
  130. while(m--){
  131. read(op),read(x1),read(y1),read(x2),read(y2);
  132. if(op==1){
  133. read(v);
  134. for(register int i=x1;i<=x2;i++){
  135. L=(i-1)*c+y1,R=(i-1)*c+y2; //注意处理技巧!!!
  136. update_add(1,1,r*c); //r*c是所有元素的范围
  137. }
  138. }
  139. else if(op==2){
  140. read(v);
  141. for(register int i=x1;i<=x2;i++){
  142. L=(i-1)*c+y1,R=(i-1)*c+y2; //注意处理技巧!!!
  143. update_set(1,1,r*c);
  144. }
  145. }
  146. else {
  147. Tmp tmp;
  148. int sum=0,mx=-inf,mi=inf;
  149. for(register int i=x1;i<=x2;i++){
  150. L=(i-1)*c+y1,R=(i-1)*c+y2; //注意处理技巧!!!
  151. tmp=query(1,1,r*c);
  152. sum+=tmp.sum;
  153. mx=max(mx,tmp.mx);
  154. mi=min(mi,tmp.mi);
  155. }
  156. printf("%d %d %d\n",sum,mi,mx);
  157. }
  158. }
  159. return 0;
  160. }

luogu题解 UVA11992 【Fast Matrix Operations】的更多相关文章

  1. UVA11992 - Fast Matrix Operations(段树部分的变化)

    UVA11992 - Fast Matrix Operations(线段树区间改动) 题目链接 题目大意:给你个r*c的矩阵,初始化为0. 然后给你三种操作: 1 x1, y1, x2, y2, v ...

  2. [uva11992]Fast Matrix Operations(多延迟标记,二维线段树,区间更新)

    题目链接:https://vjudge.net/problem/UVA-11992 题意:n*m的矩阵,每次对一个子矩阵操作,有三种操作:加x,设置为x,查询.查询返回子矩阵和.最小值.最大值 n很小 ...

  3. UVA11992 Fast Matrix Operations

    思路 注意到最多20行,拆成20颗线段树即可 注意set标记清空左右儿子的add,不要清空自己的add,因为这个set操作之后可能还有add存在这个节点上 代码 #include <cstdio ...

  4. Fast Matrix Operations

    A Simple Problem with Integers 每次将区间向下更新,或是用之前的方法,统计当前节点到父节点处的覆盖数目. #include <cstdio> #include ...

  5. UVA 11992 - Fast Matrix Operations(段树)

    UVA 11992 - Fast Matrix Operations 题目链接 题意:给定一个矩阵,3种操作,在一个矩阵中加入值a,设置值a.查询和 思路:因为最多20列,所以全然能够当作20个线段树 ...

  6. uva 11992 Fast Matrix Operations 线段树模板

    注意 setsetset 和 addvaddvaddv 标记的下传. 我们可以控制懒惰标记的优先级. 由于 setsetset 操作的优先级高于 addaddadd 操作,当下传 setsetset ...

  7. Fast Matrix Operations(UVA)11992

    UVA 11992 - Fast Matrix Operations 给定一个r*c(r<=20,r*c<=1e6)的矩阵,其元素都是0,现在对其子矩阵进行操作. 1 x1 y1 x2 y ...

  8. 线段树(多维+双成段更新) UVA 11992 Fast Matrix Operations

    题目传送门 题意:训练指南P207 分析:因为矩阵不超过20行,所以可以建20条线段的线段树,支持两个区间更新以及区间查询. #include <bits/stdc++.h> using ...

  9. UVA 11992 Fast Matrix Operations(线段树:区间修改)

    题目链接 2015-10-30 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=s ...

随机推荐

  1. Flutter移动电商实战 --(3)底部导航栏制作

    1.cupertino_IOS风格介绍 在Flutter里是有两种内置风格的: material风格: Material Design 是由 Google 推出的全新设计语言,这种设计语言是为手机.平 ...

  2. 解决 无法启动此程序,因为计算机中丢失opencv_world341.dll。请尝试重新安装改程序已解决此问题

    在运行OpenCV程序时报错:“无法启动此程序,因为计算机中丢失opencv_world341.dll.请尝试重新安装改程序已解决此问题”. 解决方法 我的bin目录是 D:\opencv\build ...

  3. ubuntu下如何安装7z压缩工具?

    答: sudo apt-get install p7zip 1. 解压 7zr x filename.7z 2. 压缩 7zr a -t7z -r filename.7z ~/filename/* 各 ...

  4. mybatis之动态SQL操作之更新

    1)  更新条件不确定,需要根据情况产生SQL语法,这种情况叫动态SQL /** * 持久层*/ public class StudentDao { /** * 动态SQL--更新 */ public ...

  5. python调试工具remote_pdb

    介绍一个调试python代码的工具:remote_pdb https://pypi.org/project/remote-pdb/ 安装 pip install remote-pdb 使用 1,设置断 ...

  6. OriginPro 9.1 科研图标绘制入门

    OriginPro 9.1 科研图标绘制入门 目的:1.介绍如何不用编程画出复杂多样的图表2.介绍OriginLab 常用功能3.科研报告时,有效绘图,省却时间 科研发展需求.反映专业形象.满足公司要 ...

  7. iOS tableHeaderView有默认高度?

    在给tableView设置tableHeaderView的时候发现,如果设置tableView.tableHeaderView = [UIView new] , 这里未设置tableView的高度,但 ...

  8. Django学习之缓存和信号

    Django学习之缓存和信号   一 缓存 由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views ...

  9. php获取服务器ip方法

    public static function getServerIp() { if(!empty($_SERVER['SERVER_ADDR'])) { return $_SERVER['SERVER ...

  10. python3速查参考- python基础 4 -> 元组 + 字典 + 字符串 的学习

    元组 元组:特点就是内容不可变,算只读的列表,可以被查询,不能被修改 a = 2, print(a) print(type(a)) b = ('a','b','c') print(b[1]) 运行结果 ...