码迷,mamicode.com
首页 > 其他好文 > 详细

UVA11992 - Fast Matrix Operations ( 线段树 + 区间修改 + 好题 )

时间:2014-10-05 15:31:38      阅读:192      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   io   os   ar   for   strong   

 

 

UVA11992 - Fast Matrix Operations ( 线段树 + 区间修改 + 好题 )

 

这是大白书上的例题,一直放着没有去A掉,这是一道线段树区间修改的好题。

线段树中需要维护三个域 ,max, min, sum,也就是区间最大值,最小值,区间和

 

题目大意:

 

r 行 c 列 的全0矩阵,支持三个操作
1 x1 y1 x2 y2 v         子矩阵(x1,y1,x2,y2)的所有元素增加v
2 x1 y1 x2 y2 v         子矩阵(x1,y1,x2,y2)的所有元素设为v
3 x1 y1 x2 y2           查询子矩阵(x1,y1,x2,y2)的max,sum,min

数据范围 0< c <=20  1< m <= 20000

 

 

分析:

可以看到矩阵的行r不超过20,白书上的思路是给每一行建立一个线段树,
这样就变为处理一维的线段树了。
具体做的时候 3  x1 y1 x2 y2  操作,
就对x1 - x2 行分别进行query(),
然后sum相加,max和min则做比较就可以了。

值得一提的是本题有两个修改操作,一个是add,一个是set
这里另外维护了两个标记setv 和 addv。
而且它们又先后顺序。
可以思考一下,set完之后不管原来是多少, 都变为set之后的值,那么add标记这种东西,也没有必要继续下传了,可以直接清除。

1:有两个标记的时候,先处理set,再处理add
2:set操作清楚addv标记,但是add操作不清楚setv操作

详见代码

 

/* ***********************************************
ID      : whiteblock63
LANG    : G++
PROG    : Uva11992-Fast Matrix Operation
DATE    : 2014-10-05 10:34:04
************************************************ */

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define CLR( a, b )        memset( a, b, sizeof(a) )
#define ls o << 1
#define rs o << 1 | 1
#define rt l, r, o
#define lson l, m, o << 1
#define rson m + 1, r, o << 1 | 1
const int NODE_SIZE = 1 << 17;
const int INF  = 0x3f3f3f3f;
int op, x1, x2, y1, y2, x, v;

// 输入挂 inline
void scan( int & x ){ char c; while( c = getchar(), c < 0 || c > 9 ); x = c - 0; while( c = getchar(), c >= 0 && c <= 9 ) x = x*10 + c - 0; }
// 线段树
struct SegTree{ int sumv[NODE_SIZE], minv[NODE_SIZE], maxv[NODE_SIZE]; int setv[NODE_SIZE], addv[NODE_SIZE]; void pushup( int l, int r, int o ){ if( l < r ){ sumv[o] = sumv[ls] + sumv[rs]; minv[o] = min( minv[ls], minv[rs] ); maxv[o] = max( maxv[ls], maxv[rs] ); } if( setv[o] >= 0 ){ minv[o] = maxv[o] = setv[o]; sumv[o] = setv[o] * ( r - l + 1 ); } if( addv[o] ){ minv[o] += addv[o]; maxv[o] += addv[o]; sumv[o] += addv[o] * ( r - l + 1 ); } } void pushdown( int o ){ if( setv[o] >= 0 ){ setv[ls] = setv[rs] = setv[o]; addv[ls] = addv[rs] = 0; setv[o] = -1;  //清除标记 } if( addv[o] ){ addv[ls] += addv[o]; addv[rs] += addv[o]; addv[o] = 0;   //清除标记 } } void update( int l, int r, int o ){ if( y1 <= l && r <= y2 ){ if( op == 1 ) addv[o] += v; else setv[o] = v, addv[o] = 0; }else{ pushdown( o ); int m = l + r >> 1; if( y1 <= m ) update( lson ); else pushup( lson ); if( y2 > m ) update( rson ); else pushup( rson ); } pushup( rt ); } void query( int l, int r, int o, int& ssum, int& smin, int& smax ){ pushup( rt );  // 处理被pushdown下来的标记 if( y1 <= l && r <= y2 ){ ssum = sumv[o]; smin = minv[o]; smax = maxv[o]; }else{ pushdown( o ); int m = l + r >> 1; int lsum = 0, lmin = INF, lmax = -INF; int rsum = 0, rmin = INF, rmax = -INF; if( y1 <= m ) query( lson, lsum, lmin, lmax ); else pushup( lson ); if( y2 > m ) query( rson, rsum, rmin, rmax ); else pushup( rson ); ssum = lsum + rsum; smin = min( lmin, rmin ); smax = max( lmax, rmax ); } } }; const int MAXR = 20 + 5; SegTree tree[MAXR]; int main() { int r, c, m; while( ~scanf( "%d %d %d", &r, &c, &m ) ){ CLR( tree, 0 ); for( x = 1; x <= r; ++x ){ CLR( tree[x].setv, -1 ); tree[x].setv[1] = 0; } while( m-- ){ scan( op ); scan( x1 ); scan( y1 ); scan( x2 ); scan( y2 ); if( op < 3 ){ scan( v ); for( x = x1; x <= x2; ++x ) tree[x].update( 1, c, 1 ); }else{ int gsum = 0, gmin = INF, gmax = -INF; for( x = x1; x <= x2; ++x ){ int ssum, smin, smax; tree[x].query( 1, c, 1, ssum, smin, smax ); gsum += ssum; gmin = min( gmin, smin ); gmax = max( gmax, smax ); } printf("%d %d %d\n", gsum, gmin, gmax ); } } } return 0; }

 

UVA11992 - Fast Matrix Operations ( 线段树 + 区间修改 + 好题 )

标签:style   blog   http   color   io   os   ar   for   strong   

原文地址:http://www.cnblogs.com/BigBallon/p/4006925.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!