UVA 11992 - Fast Matrix Operations

Fast Matrix Operations


There is a matrix containing at most 106 elements divided
into r rows and c columns. Each element has a location (x,y) where
1<=x<=r,1<=y<=c. Initially, all the elements are zero. You need to
handle four kinds of operations:

1 x1 y1 x2 y2 v

Increment each element (x,y) in submatrix (x1,y1,x2,y2) by v (v>0)

2 x1 y1 x2 y2 v

Set each element (x,y) in submatrix (x1,y1,x2,y2) to v

3 x1 y1 x2 y2

Output the summation, min value and max value of submatrix (x1,y1,x2,y2)

In the above descriptions, submatrix (x1,y1,x2,y2) means all the elements
(x,y) satisfying x1<=x<=x2 and y1<=x<=y2. It is guaranteed that
1<=x1<=x2<=r, 1<=y1<=y2<=c. After any operation, the sum of
all the elements in the matrix does not exceed 109.

Input


There are several test cases. The first line of each case contains three
positive integers r, c, m, where m (1<=m<=20,000) is the number of
operations. Each of the next m lines contains a query. There will be at most
twenty rows in the matrix. The input is terminated by end-of-file (EOF). The
size of input file does not exceed 500KB.

Output

For each type-3 query, print the summation, min and max.

Sample Input

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

Output for the Sample Input

45 0 5
78 5 7
69 2 7
39 2 7

这两天一直再搞线段树,没写好一道题,加上学业一下子忙起来,没来得及更新博客,今天终于把一道题写好了.此题是线段树的综合应用,题很好,对区间维护要求大.要特别注意区间累加和重置操作的关系,有无影响。


/*
* @author Panoss
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<ctime>
#include<stack>
#include<queue>
#include<list>
using namespace std;
#define DBG 0
#define fori(i,a,b) for(int i = (a); i < (b); i++)
#define forie(i,a,b) for(int i = (a); i <= (b); i++)
#define ford(i,a,b) for(int i = (a); i > (b); i--)
#define forde(i,a,b) for(int i = (a); i >= (b); i--)
#define forls(i,a,b,n) for(int i = (a); i != (b); i = n[i])
#define mset(a,v) memset(a, v, sizeof(a))
#define mcpy(a,b) memcpy(a, b, sizeof(a))
#define dout DBG && cerr << __LINE__ << " >>| "
#define checkv(x) dout << #x"=" << (x) << " | "<<endl
#define checka(array,a,b) if(DBG) { \
dout << #array"[] | " << endl; forie(i, a, b) cerr << "[" << i << "]=" << array[i] << " |" << ((i - (a)+1) % 5 ? " " : "\n"); if (((b)-(a)+1) % 5) cerr << endl; }
#define redata(T, x) T x; cin >> x
#define MIN_LD -2147483648
#define MAX_LD 2147483647
#define MIN_LLD -9223372036854775808
#define MAX_LLD 9223372036854775807
#define MAX_INF 18446744073709551615
inline int reint() { int d; scanf("%d", &d); return d; }
inline long relong() { long l; scanf("%ld", &l); return l; }
inline char rechar() { scanf(" "); return getchar(); }
inline double redouble() { double d; scanf("%lf", &d); return d; }
inline string restring() { string s; cin >> s; return s; }

#define MAX_TREE_NODE 50000 ///树结点个数

struct Segment_Tree
{
int L, R; ///左,右区间
long min_value, max_value; ///区间最小值,最大值;
long sum; ///区间和
bool add_flag; ///区间是否增个某个数值标志
long add_value; ///区间增量
bool set_flag; ///区间是否重置为某个数值标志
long set_value; ///设置值
struct Segment_Tree * left; ///左儿子
struct Segment_Tree * right; ///右儿子
};

Segment_Tree Tree[25][2 * MAX_TREE_NODE + 5];

int Tree_node_number = 1; ///结点编号,1号为根结点

int Mid(Segment_Tree * root) { return (root->L + (root->R - root->L) / 2); }

void Build_Tree(Segment_Tree * root, int left, int right,int k) ///建树,第k棵树
{
root->L = left;
root->R = right;
root->max_value = MIN_LD;
root->min_value = MAX_LD;
root->sum = 0;
root->add_value = 0;
root->add_flag = false;
root->set_value = 0;
root->set_flag = false;
root->left = NULL;
root->right = NULL;
if (left == right) return;
Tree_node_number++;
root->left = Tree[k] + Tree_node_number;
Tree_node_number++;
root->right = Tree[k] + Tree_node_number;
Build_Tree(root->left, left, (left + right) / 2,k);
Build_Tree(root->right, (left + right) / 2 + 1, right,k);
}

void updata(Segment_Tree * root) ///维护根结点的信息
{
if (root->R > root->L)
{
root->max_value = max(root->left->max_value, root->right->max_value);
root->min_value = min(root->left->min_value, root->right->min_value);
root->sum = root->left->sum + root->right->sum;
}

if (root->set_flag)
{
root->max_value = root->set_value;
root->min_value = root->set_value;
root->sum = root->set_value * (root->R - root->L + 1);
}

if (root->add_flag)
{
root->max_value += root->add_value;
root->min_value += root->add_value;
root->sum += root->add_value * (root->R - root->L + 1);
}

}

void pushdown(Segment_Tree *root) ///传递标记
{
if (root->set_flag)
{
root->left->set_value = root->set_value;
root->left->set_flag = true;
root->left->add_value = 0;
root->left->add_flag = false;

root->right->set_value = root->set_value;
root->right->set_flag = true;
root->right->add_value = 0;
root->right->add_flag = false;

root->set_flag = false;
root->set_value = 0;
}

if (root->add_flag)
{
root->left->add_value += root->add_value;
root->left->add_flag = true;

root->right->add_value += root->add_value;
root->right->add_flag = true;

root->add_flag = false;
root->add_value = 0;
}

}

void Add_value(Segment_Tree * root, int i, int j, int value) ///为区间i,j每个元素加value
{
if (i <= root->L && root->R <= j)
{
root->add_flag = true;
root->add_value += value;
}
else
{
pushdown(root);

if (i <= Mid(root))
{
Add_value(root->left, i, j, value);
}
else
{
updata(root->left);
}
if (Mid(root) < j)
{
Add_value(root->right, i, j, value);
}
else
{
updata(root->right);
}
}

updata(root);
}

void Set_value(Segment_Tree * root, int i, int j, int value) ///重置区间i,j每个元素为value
{
if (i <= root->L && root->R <= j)
{
root->set_flag = true;
root->set_value = value;
root->add_value = 0;
root->add_flag = false;
}
else
{
pushdown(root);

if (i <= Mid(root))
{
Set_value(root->left, i, j, value);
}
else
{
updata(root->left);
}
if (Mid(root) < j)
{
Set_value(root->right, i, j, value);
}
else
{
updata(root->right);
}
}

updata(root);
}

void Change_node(Segment_Tree * root, int number, int value) ///修改数据 a[number] = value;
{
if (root->L == number && root->R == number) ///叶子结点,直接修改,更新最大值最小值为value,区间和也是value
{
root->sum = root->max_value = root->min_value = value;
}
else
{
if (number <= Mid(root))
{
Change_node(root->left, number, value);
}
else
{
Change_node(root->right, number, value);
}

updata(root);
}
}

long Query_min_value(Segment_Tree * root, int i, int j,int add_total) ///查询区间i,j最小值
{
long ans_min = MAX_LD;

if (root->set_flag)
{
long total_value = root->set_value + add_total;
if (root->add_flag) total_value += root->add_value;

ans_min = min(ans_min, total_value);
}

else if (i <= root->L && root->R <= j)
{
ans_min = min(ans_min, root->min_value + add_total);
}
else
{
if (root->add_flag)
{
long left_min = MAX_LD, right_min = MAX_LD;
if (i <= Mid(root))
left_min = Query_min_value(root->left, i, j, add_total + root->add_value);
if (j > Mid(root))
right_min = Query_min_value(root->right, i, j, add_total + root->add_value);
ans_min = min(left_min, right_min);
}
else
{
long left_min = MAX_LD, right_min = MAX_LD;
if (i <= Mid(root))
left_min = Query_min_value(root->left, i, j, add_total);
if (j > Mid(root))
right_min = Query_min_value(root->right, i, j, add_total);
ans_min = min(left_min, right_min);
}

}
return ans_min;
}

long Query_max_value(Segment_Tree * root, int i, int j,int add_total) ///查询区间i,j最大值
{

long ans_max = MIN_LD;

if (root->set_flag)
{
long total_value = root->set_value + add_total;
if (root->add_flag) total_value += root->add_value;

ans_max = max(ans_max, total_value);
}

else if (i <= root->L && root->R <= j)
{
ans_max = max(ans_max, root->max_value + add_total);
}
else
{
if (root->add_flag)
{
long left_max = MIN_LD, right_max = MIN_LD;
if (i <= Mid(root))
left_max = Query_max_value(root->left, i, j, add_total + root->add_value);
if (j > Mid(root))
right_max = Query_max_value(root->right, i, j, add_total + root->add_value);
ans_max = max(left_max, right_max);
}
else
{
long left_max = MIN_LD, right_max = MIN_LD;
if (i <= Mid(root))
left_max = Query_max_value(root->left, i, j, add_total);
if (j > Mid(root))
right_max = Query_max_value(root->right, i, j, add_total);
ans_max = max(left_max, right_max);
}
}
return ans_max;
}

long Get_sum(Segment_Tree *root, int i, int j, int add_total) ///求区间i,j的和
{
long ans_sum = 0;

if (root->set_flag)
{
long value_total = root->set_value + add_total;
if (root->add_flag) value_total += root->add_value;

ans_sum += value_total * ( min(root->R,j) - max(root->L,i) + 1);

}

else if (i <= root->L && root->R <= j)
{
ans_sum += root->sum + add_total * (root->R - root->L + 1);
}
else
{
if (root->add_flag)
{
if(i <= Mid(root) )
ans_sum += Get_sum(root->left, i, j, add_total + root->add_value);
if(Mid(root) < j)
ans_sum += Get_sum(root->right, i, j, add_total + root->add_value);
}
else
{
if (i <= Mid(root))
ans_sum += Get_sum(root->left, i, j, add_total );
if (Mid(root) < j)
ans_sum += Get_sum(root->right, i, j, add_total );
}
}
return ans_sum;
}

int main()
{
int r, c, m, op;
int x1, y1, x2, y2, value;
while (scanf("%d%d%d", &r, &c, &m) == 3)
{
mset(Tree,0);

forie(i, 1, r) ///为每一行建一棵线段树
{
Tree_node_number = 1;
Build_Tree(Tree[i] + 1, 1, c, i);
}
forie(i, 1, r) ///为每一棵线段树插入每个元素为0
{
Set_value(Tree[i] + 1, 1, c, 0);///直接每行全部清0,或者调用Chang_node修改数据
}

forie(T, 1, m)
{
scanf("%d", &op);
if (op == 1)
{
scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &value);
forie(i, x1, x2)
{
Add_value(Tree[i] + 1, y1, y2, value);
}
}
if (op == 2)
{
scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &value);
forie(i, x1, x2)
{
Set_value(Tree[i] + 1, y1, y2, value);
}
}
if (op == 3)
{
long ans_sum = 0, ans_min = MAX_LD, ans_max = MIN_LD;

scanf("%d%d%d%d", &x1, &y1, &x2, &y2);

forie(i, x1, x2)
{
ans_sum += Get_sum(Tree[i] + 1, y1, y2, 0);
}

forie(i, x1, x2)
{
ans_min = min(ans_min, Query_min_value(Tree[i] + 1, y1, y2, 0));
}

forie(i, x1, x2)
{
ans_max = max(ans_max, Query_max_value(Tree[i] + 1, y1, y2, 0));
}

printf("%ld %ld %ld\n", ans_sum, ans_min, ans_max);
}
}
}
return 0;
}

UVA 11992 - Fast Matrix Operations

时间: 2024-07-31 05:56:29

UVA 11992 - Fast Matrix Operations的相关文章

UVa 11992 Fast Matrix Operations (线段树)

Fast Matrix Operations Description There is a matrix containing at most 106 elements divided into r rows and c columns. Each element has a location (x, y) where 1 ≤ x ≤ r, 1 ≤ y ≤ c. Initially, all the elements are zero. You need to handle four kinds

UVa 11992 Fast Matrix Operations(线段树双懒操作,二维转一维)

题意:给个r*c的矩形,三种操作,将一个子矩形权值+v,将一个子矩阵权值赋值为v,查询一个子矩阵sum,max,min.起初矩阵权值为0,保证r<=20,r*c<=1e6,操作次数不超过10000 链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18697 题解:将二维转一维,设当前点为(x,y),则它在线段树上的点为(x-1)*c+y,由于行不超过20行,不妨枚举每一行,去操作.对于一维的线段树,要进行赋值,加法

UVA 11992 Fast Matrix Operations (降维)

题意:对一个矩阵进行子矩阵操作. 元素对多有1e6个,树套树不好开(我不会),把二维坐标化成一维的,一个子矩阵操作分解成多条线段的操作. 一次操作的复杂度是RlogC,很容易找到极端的数据(OJ上实测没有),如果判断一下然后建树复杂度是min(RlogC,ClogR). 代码中结点没有保存l和r,而且询问是保存在全局变量中,这样做比较省空间.但是也有缺点,比如推区间结点数量的时候会麻烦一点. #include<bits/stdc++.h> using namespace std; const

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

题目传送门 题意:训练指南P207 分析:因为矩阵不超过20行,所以可以建20条线段的线段树,支持两个区间更新以及区间查询. #include <bits/stdc++.h> using namespace std; #define lson l, mid, o << 1 #define rson mid + 1, r, o << 1 | 1 typedef long long ll; const int INF = 0x3f3f3f3f; const int N =

UVA 11992(Fast Matrix Operations-线段树区间加&amp;改)[Template:SegmentTree]

Fast Matrix Operations There is a matrix containing at most 106 elements divided into r rows and c columns. Each element has a location (x,y) where 1<=x<=r,1<=y<=c. Initially, all the elements are zero. You need to handle four kinds of operati

【UVA】11992 - Fast Matrix Operations(线段树模板)

基本的线段树,需要注意的是由于有set和add操作,懒惰标记下推的时候,优先递推set,之后递推add,每次执行set操作将add标记清0 WA了好几次是因为计算那一段的时候出问题了,可笑的是我对着模板找了一个多小时的错. #include<cstdio> #include<cmath> #include<queue> #include<stack> #include<map> #include<algorithm> using na

【UVA】11992 - Fast Matrix Operations(段树模板)

主体段树,要注意,因为有set和add操作,当慵懒的标志下推.递归优先set,后复发add,每次运行set行动add马克清0 WA了好几次是由于计算那一段的时候出问题了,可笑的是我对着模板找了一个多小时的错. #include<cstdio> #include<cmath> #include<queue> #include<stack> #include<map> #include<algorithm> using namespace

uva 1401 Fast Matrix Operations 快速矩阵操作 (线段树 区间修改和查询)

题意:给一个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)的元素和.最小值.最大值. 子矩阵(x1 y1 x2 y2)是指满足 x1 <= x <= x2, y1 <= y <= y2的所有元素(x,y). 矩阵不超过20行,矩阵总元素可多达10^6个. 思路

Fast Matrix Operations(UVA)11992

UVA 11992 - Fast Matrix Operations 给定一个r*c(r<=20,r*c<=1e6)的矩阵,其元素都是0,现在对其子矩阵进行操作. 1 x1 y1 x2 y2 val 表示将(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素add上val: 2 x1 y1 x2 y2 val 表示将(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素set为val: 3 x1 y1 x2 y2 val 表示输