UVa 11992 Fast Matrix Operations (线段树,区间修改)
题意:给出一个row*col的全0矩阵,有三种操作
1 x1 y1 x2 y2 v:将x1 <= row <= x2, y1 <= col <= y2里面的点全部增加v;
2 x1 y1 x2 y2 v:将x1 <= row <= x2, y1 <= col <= y2里面的点全部变成v;
3 x1 y1 x2 y2:输出x1 <= row <= x2, y1 <= col <= y2的点的和,最小值和最大值进行输出。
析:一看题目,很容易看出来是线段树,可是。。。竟然要维护三个值,而且还有两种操作,增加或修改。。。。这日子没法过!!!一头雾水,懵逼中。。。
一想这也太恐怖了吧,这怎么算,看着挺简单,做起来就恶心。本想都分开写,又觉得可能是会TLE,就只能凑合写了。。。写完后,一直崩,无法正常运行啊,原来是越界了,改完后又是bug多多啊,结果WA了好几次,查了好久,原来以为是数组开小了,后来加大也不对,差点就崩溃了,反复调整,终于过了,关键是我错了样例还一样过了。。。样例真是水,后台数据真是坑。。。
分析一下这个题,矩阵虽然不超过20行,但是却有多达10的6次方个元素,可以建立一个一维线段树,把每行都拼起来。
然后这个题有两个恶心的操作,set和add,所以我们就是做两个标记setv和addv,要不然一次更新都要改,时间会受不了,并且如果两个标记都存在进,先执行set再执行add,这个在pushdown中体现。
注意两个update(updateadd和updateset)的递归边界,对于updateset操作要清除结点上的addv标记;但是对于updateadd操作则不清除setv标记,再就是不要越界,算好区间的端点。可以用位运算,简化一下代码。
代码如下:
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #define lson l, m, rt<<1
- #define rson m+1, r, rt<<1|1
- using namespace std;
- const int maxn = 1000005;
- const int INF = 0x3f3f3f3f;
- int sum[maxn<<2], minv[maxn<<2], maxv[maxn<<2], setv[maxn<<2], addv[maxn<<2];
- int minn, maxm;
- void pushup(int rt){
- sum[rt] = sum[rt<<1] + sum[rt<<1|1];
- minv[rt] = min(minv[rt<<1], minv[rt<<1|1]);
- maxv[rt] = max(maxv[rt<<1], maxv[rt<<1|1]);
- }
- void pushdown(int rt, int len){
- int l = rt<<1, r = rt<<1|1;
- if(setv[rt] >= 0){//先考虑set
- addv[l] = addv[r] = 0;
- maxv[l] = maxv[r] = minv[l] = minv[r] = setv[rt];
- sum[l] = (len - (len>>1)) * setv[rt];
- sum[r] = (len>>1) * setv[rt];
- setv[l] = setv[r] = setv[rt];
- setv[rt] = -1;
- }
- if(addv[rt]){//再考虑add
- sum[l] += (len - len/2) * addv[rt]; sum[r] += (len/2) * addv[rt];
- minv[l] += addv[rt]; minv[r] += addv[rt];
- maxv[l] += addv[rt]; maxv[r] += addv[rt];
- addv[l] += addv[rt]; addv[r] += addv[rt];
- addv[rt] = 0;
- }
- }
- void build(int l, int r, int rt){//建树
- if(l == r){ sum[rt] = minv[rt] = maxv[rt] = 0; return ; }
- int m = (l + r) >> 1;
- build(lson);
- build(rson);
- pushup(rt);
- }
- void updateset(int L, int R, int val, int l, int r, int rt){//set操作
- if(L <= l && R >= r){
- sum[rt] = (r-l+1) * val;
- minv[rt] = maxv[rt] = val;
- addv[rt] = 0;//清除标记
- setv[rt] = val;
- return ;
- }
- pushdown(rt, r-l+1);
- int m = (l+r) >> 1;
- if(L <= m) updateset(L, R, val, lson);
- if(R > m) updateset(L, R, val, rson);
- pushup(rt);
- }
- void updateadd(int L, int R, int val, int l, int r, int rt){//add操作
- if(L <= l && R >= r){
- addv[rt] += val;
- sum[rt] += (r-l+1) * val;
- minv[rt] += val; maxv[rt] += val;
- return ;//不清除标记
- }
- pushdown(rt, r-l+1);
- int m = (r+l) >> 1;
- if(L <= m) updateadd(L, R, val, lson);
- if(R > m) updateadd(L, R, val, rson);
- pushup(rt);
- }
- int query(int L, int R, int l, int r, int rt){
- if(L <= l && R >= r){
- minn = min(minn, minv[rt]);
- maxm = max(maxm, maxv[rt]);
- return sum[rt];
- }
- pushdown(rt, r-l+1);
- int m = (r+l) >> 1;
- int ans = 0;
- if(L <= m) ans += query(L, R, lson);
- if(R > m) ans += query(L, R, rson);
- return ans;
- }
- int main(){
- // freopen("in.txt", "r", stdin);
- int r, c, q;
- while(~scanf("%d %d %d", &r, &c, &q)){
- memset(addv, 0, sizeof(addv));
- memset(setv, -1, sizeof(setv));
- memset(sum, 0, sizeof(sum));
- build(1, r*c, 1);
- int x1, x2, y1, y2, val, num;
- while(q--){
- scanf("%d %d %d %d %d", &num, &x1, &y1, &x2, &y2);
- --x1; --x2;//注意不要越界,算好区间端点
- if(1 == num){
- scanf("%d", &val);
- for(int i = x1; i <= x2; ++i)
- updateadd(i*c+y1, i*c+y2, val, 1, r*c, 1);
- // puts("++");
- }
- else if(2 == num){
- scanf("%d", &val);
- for(int i = x1; i <= x2; ++i)
- updateset(i*c+y1, i*c+y2, val, 1, r*c, 1);
- }
- else if(3 == num){
- int ans = 0;
- minn = INF, maxm = -INF;//全局变量,初始化一下
- for(int i = x1; i <= x2; ++i)
- ans += query(i*c+y1, i*c+y2, 1, r*c, 1);
- printf("%d %d %d\n", ans, minn, maxm);
- }
- }
- }
- return 0;
- }
UVa 11992 Fast Matrix Operations (线段树,区间修改)的更多相关文章
- uva 11992 Fast Matrix Operations 线段树模板
注意 setsetset 和 addvaddvaddv 标记的下传. 我们可以控制懒惰标记的优先级. 由于 setsetset 操作的优先级高于 addaddadd 操作,当下传 setsetset ...
- UVA 11992 - Fast Matrix Operations(段树)
UVA 11992 - Fast Matrix Operations 题目链接 题意:给定一个矩阵,3种操作,在一个矩阵中加入值a,设置值a.查询和 思路:因为最多20列,所以全然能够当作20个线段树 ...
- UVA 11992 Fast Matrix Operations(线段树:区间修改)
题目链接 2015-10-30 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=s ...
- 线段树(多维+双成段更新) UVA 11992 Fast Matrix Operations
题目传送门 题意:训练指南P207 分析:因为矩阵不超过20行,所以可以建20条线段的线段树,支持两个区间更新以及区间查询. #include <bits/stdc++.h> using ...
- UVA 11992 Fast Matrix Operations (二维线段树)
解法:因为至多20行,所以至多建20棵线段树,每行建一个.具体实现如下,有些复杂,慢慢看吧. #include <iostream> #include <cstdio> #in ...
- uva 11992 - Fast Matrix Operations
简单的线段树的题: 有两种方法写这个题,目前用的熟是这种慢点的: 不过不知道怎么老是T: 感觉网上A过的人的时间度都好小,但他们都是用数组实现的 难道是指针比数组慢? 好吧,以后多用数组写写吧! 超时 ...
- UVA 11992 Fast Matrix Operations (降维)
题意:对一个矩阵进行子矩阵操作. 元素最多有1e6个,树套树不好开(我不会),把二维坐标化成一维的,一个子矩阵操作分解成多条线段的操作. 一次操作的复杂度是RlogC,很容易找到极端的数据(OJ上实测 ...
- UVA11992 - Fast Matrix Operations(段树部分的变化)
UVA11992 - Fast Matrix Operations(线段树区间改动) 题目链接 题目大意:给你个r*c的矩阵,初始化为0. 然后给你三种操作: 1 x1, y1, x2, y2, v ...
- 题解报告:hdu 1698 Just a Hook(线段树区间修改+lazy懒标记的运用)
Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing for m ...
随机推荐
- 转。。原理同样支持 delphi
我用C#导出excel 带图片,用office2003 正常,但换成office 2007 时,我指定多个单元格分别插入图片,这个图片不在此单元格内,这些图片全都集中在一起,在一个位置上.很奇怪,看起 ...
- unity 加载读取外部XML
cfg.xml <rootNode> <category name="网站"> <item name="mainPage"> ...
- Hadoop主要架构
主要架构图 各部分作用 * Core:核心支持,内核代码 * MapReduce:映射数据 * HDFS:文件存储 * ZooKepper:服务器节点和进程通信的协调工具 * Pig:支持用户和Map ...
- Tomcat数据库连接池配置
Tomcat数据库连接池配置 1. Server.xml的配置 (1)找到tomcat所在目录下的conf\server.xml文件 (2)在文件最后一个</host> ...
- C#四舍五入说明
string.Format("{0:N2}", d) 与 Math.Round(d, 2).ToString() 不总是相等 string.Format("{0:N2}& ...
- STC-51开发板-单片机控制数码管&按键&点阵综合操作
操作: 实现按下一个按键,对应的数码管和点阵显示相应的数字 代码: /* *******************数码管按键综合项目********************* */ #include ...
- tesseract 4.0 编译安装(CentOS)
1.安装依赖工具 yum install autoconf automake libtool libjpeg-devel libpng-devel libtiff-devel zlib-devel 2 ...
- fiddler 发送get请求
点击Composer 点击执行(Execute) \ 这里演示的是带cookie
- 如何快速实现一个command
新建一个类,实现icoomand接口 定义一个委托,为测试方便,先不考虑CanExecute的情况. 越简单越好. 代码如下: public class ExitHandler : ICommand ...
- win7卸载打印机驱动
无法删除的话停止Print Spooler服务 删除PRINTERS文件夹下面的文件 C:\Windows\System32\spool\PRINTERS目录下所有的文件,重新启动服务:print s ...