标签: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