二维线段树 UVa 11992 - Fast Matrix Operations
给一个总元素个数为n(n≤1000000) 的矩阵,矩阵长度为 (r≤20),宽度为 c,矩阵初始值全为整数 0。定义一个子矩阵 (x1,y1),(x2,y2)(包括边界),操作有三种:
将子矩阵的每个元素加上一个值v(v>0)。
将子矩阵的每个元素赋值为v(v≥0)。
查询子矩阵所有元素的和,最小值,最大值。
样例输入
4 4 8
1 1 2 4 4 5
3 2 1 4 4
1 1 1 3 4 2
3 1 2 4 4
3 1 1 3 4
2 2 1 4 4 2
3 1 2 4 4
1 1 1 4 3 3
样例输出
45 0 5
78 5 7
69 2 7
39 2 7
附加输入
1 2 8
1 1 1 1 2 1
3 1 1 1 2
1 1 1 1 1 1
3 1 1 1 2
2 1 2 1 2 3
3 1 1 1 2
1 1 1 1 2 3
3 1 1 1 2
附加输出
2 1 1
3 1 2
5 2 3
11 5 6
https://blog.sengxian.com/solutions/uva-11992
#include <cstdio>
#include <cstring>
#define clear( A , X ) memset ( A , X , sizeof A )
#define lson l , m , o << 1
#define rson m + 1 , r , o << 1 | 1
const int maxR = 22 ;
const int maxC = 200005 ;
const int oo = 0x3f3f3f3f ;
int max[maxR][maxC] , min[maxR][maxC] , sum[maxR][maxC] ;
int add[maxR][maxC] , set[maxR][maxC] ;
int Min ( const int X , const int Y )
{
if ( X < Y ) return X ;
return Y ;
}
int Max ( const int X , const int Y )
{
if ( X > Y ) return X ;
return Y ;
}
void PushUp ( int x , int o )
{
sum[x][o] = sum[x][o << 1] + sum[x][o << 1 | 1] ;
min[x][o] = Min ( min[x][o << 1] , min[x][o << 1 | 1] ) ;
max[x][o] = Max ( max[x][o << 1] , max[x][o << 1 | 1] ) ;
}
void PushDown ( int x , int l , int r , int o )
{
int m = ( l + r ) >> 1 ;
if ( set[x][o] ) //如果存在强制归为某个数的操作
{
int tmp = set[x][o] ;
set[x][o << 1] = tmp ;//下放到子结点
min[x][o << 1] = tmp ;//最小值,最大值都发生变化
max[x][o << 1] = tmp ;
sum[x][o << 1] = tmp * ( m - l + 1 ) ;
//区间总和也要发生变化
add[x][o << 1] = 0 ;
//从前打过的加法的标记归0
set[x][o << 1 | 1] = tmp ;
min[x][o << 1 | 1] = tmp ;
max[x][o << 1 | 1] = tmp ;
sum[x][o << 1 | 1] = tmp * ( r - m ) ;
add[x][o << 1 | 1] = 0 ;
set[x][o] = 0 ;
}
if ( add[x][o] )
{
int tmp = add[x][o] ;
add[x][o << 1] += tmp ;
min[x][o << 1] += tmp ;
max[x][o << 1] += tmp ;
sum[x][o << 1] += tmp * ( m - l + 1 ) ;
add[x][o << 1 | 1] += tmp ;
min[x][o << 1 | 1] += tmp ;
max[x][o << 1 | 1] += tmp ;
sum[x][o << 1 | 1] += tmp * ( r - m ) ;
add[x][o] = 0 ;
}
}
void Build ( int x , int l , int r , int o )
//x代表这是第多少个线段树,它的o这个结点管辖[L,R]这一段
{
set[x][o] = add[x][o] = 0 ;
if ( l == r )
{
min[x][o] = max[x][o] = sum[x][o] = 0 ;
return ;
}
int m = ( l + r ) >> 1 ;
Build ( x , lson ) ;
Build ( x , rson ) ;
}
void Set ( int L , int R , int v , int x , int l , int r , int o )
{
if ( L <= l && r <= R )
{
add[x][o] = 0 ;
set[x][o] = v ;
min[x][o] = v ;
max[x][o] = v ;
sum[x][o] = v * ( r - l + 1 ) ;
return ;
}
PushDown ( x , l , r , o ) ;
int m = ( l + r ) >> 1 ;
if ( L <= m )
Set ( L , R , v , x , lson ) ;
if ( m < R )
Set ( L , R , v , x , rson ) ;
PushUp ( x , o ) ;
}
void Add ( int L , int R , int v , int x , int l , int r , int o ) {
if ( L <= l && r <= R ) {
add[x][o] += v ;
min[x][o] += v ;
max[x][o] += v ;
sum[x][o] += v * ( r - l + 1 ) ;
return ;
}
PushDown ( x , l , r , o ) ;
int m = ( l + r ) >> 1 ;
if ( L <= m ) Add ( L , R , v , x , lson ) ;
if ( m < R ) Add ( L , R , v , x , rson ) ;
PushUp ( x , o ) ;
}
int ansmin , ansmax , anssum ;
void Query ( int L , int R , int x , int l , int r , int o ) {
if ( L <= l && r <= R ) {
ansmin = Min ( ansmin , min[x][o] ) ;
ansmax = Max ( ansmax , max[x][o] ) ;
anssum += sum[x][o] ;
return ;
}
PushDown ( x , l , r , o ) ;
int m = ( l + r ) >> 1 ;
if ( L <= m ) Query ( L , R , x , lson ) ;
if ( m < R ) Query ( L , R , x , rson ) ;
}
void work () {
int n , m , q , ch , x1 , x2 , y1 , y2 , v ;
while ( ~scanf ( "%d%d%d" , &n , &m , &q ) )
{
for ( int i = 1 ; i <= n ; ++ i )
Build ( i , 1 , m , 1 ) ;
while ( q -- )
{
scanf ( "%d" , &ch ) ;
if ( 1 == ch ) {
scanf ( "%d%d%d%d%d" , &x1 , &y1 , &x2 , &y2 , &v ) ;
for ( int i = x1 ; i <= x2 ; ++ i )
{
Add ( y1 , y2 , v , i , 1 , m , 1 ) ;
//在第i个线段树上[y1,y2]这一段上加上数字v
}
}
if ( 2 == ch )
{
scanf ( "%d%d%d%d%d" , &x1 , &y1 , &x2 , &y2 , &v ) ;
for ( int i = x1 ; i <= x2 ; ++ i ) {
Set ( y1 , y2 , v , i , 1 , m , 1 ) ;
}
}
if ( 3 == ch )
{
scanf ( "%d%d%d%d" , &x1 , &y1 , &x2 , &y2 ) ;
ansmin = oo ;
ansmax = 0 ;
anssum = 0 ;
for ( int i = x1 ; i <= x2 ; ++ i )
{
Query ( y1 , y2 , i , 1 , m , 1 ) ;
}
printf ( "%d %d %d\n" , anssum , ansmin , ansmax ) ;
}
}
}
}
int main () {
work () ;
return 0 ;
}
————————————————
版权声明:本文为CSDN博主「poursoul」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013368721/article/details/32695823

浙公网安备 33010602011771号