题目链接 2015-10-30 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3143
给你一个矩阵,矩阵的每个元素初始值均为0
进行m次操作,操作共有三种类型,分别用1,2,3表示
操作一:子矩阵(x1, y1, x2, y2)的所有元素增加v
操作二:子矩阵(x1, y1, x2, y2)的所有元素设为v
操作三:查询子矩阵(x1, y1, x2, y2)的元素和,最小值和最大值
矩阵只有20行,可以每行建一棵线段树(建议直接转为一维)
#include <iostream> #include <cstring> #include <algorithm> #define maxn 3000100 #define inf 1000000000 #define LL(x) x<<1 #define RR(x) x<<1|1 using namespace std; typedef long long LL; //variable define struct tree { int l, r; int mi, ma, sum; int add, set; }; tree node[maxn]; int row, col, m, ans_mi, ans_ma, ans_sum; //function define void push_down(int x); void push_up(int x); void build_tree(int left, int right, int x); void query(int left, int right, int x); void update_set(int left, int right, int x, int val); void update_add(int left, int right, int x, int val); int main(void) { while (scanf("%d %d %d", &row, &col, &m) != EOF) { build_tree( 1, row*col, 1); int op, x1, y1, x2, y2, val; while (m--) { scanf("%d", &op); if (op == 1) { scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &val); for (int i = x1; i <= x2; ++i) update_add( (i-1)*col + y1, (i-1)*col + y2, 1, val); } else if (op == 2) { scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &val); for (int i = x1; i <= x2; ++i) update_set( (i-1)*col + y1, (i-1)*col + y2, 1, val); } else { scanf("%d %d %d %d", &x1, &y1, &x2, &y2); ans_sum = 0; ans_ma = -inf; ans_mi = inf; for (int i = x1; i <= x2; ++i) query( (i-1)*col + y1, (i-1)*col + y2, 1); //output printf("%d %d %d\n", ans_sum, ans_mi, ans_ma); } } } return 0; } void build_tree(int left, int right, int x) { node[x].l = left; node[x].r = right; node[x].ma = node[x].mi = node[x].sum = 0; node[x].add = 0; node[x].set = -1; if (left == right) return; int lx = LL(x); int rx = RR(x); int mid = left + (right - left)/2; build_tree(left, mid, lx); build_tree(mid + 1, right, rx); //push_up(x); } void push_up(int x) { if (node[x].l >= node[x].r) return; int lx = LL(x); int rx = RR(x); node[x].ma = max( node[lx].ma, node[rx].ma); node[x].mi = min( node[lx].mi, node[rx].mi); node[x].sum = node[lx].sum + node[rx].sum; } void push_down(int x) { if (node[x].l >= node[x].r) return; int lx = LL(x); int rx = RR(x); if (node[x].set != -1) { node[lx].set = node[rx].set = node[x].set; node[lx].mi = node[rx].mi = node[x].set; node[lx].ma = node[rx].ma = node[x].set; node[lx].add = node[rx].add = 0; node[lx].sum = (node[lx].r - node[lx].l + 1) * node[x].set; node[rx].sum = (node[rx].r - node[rx].l + 1) * node[x].set; } if (node[x].add > 0) { LL tmp = node[x].add; node[lx].add += tmp; node[rx].add += tmp; node[lx].ma += tmp; node[rx].ma += tmp; node[lx].mi += tmp; node[rx].mi += tmp; node[lx].sum += (tmp * (node[lx].r - node[lx].l + 1)); node[rx].sum += (tmp * (node[rx].r - node[rx].l + 1)); } } void update_set(int left, int right, int x, int val) { if (node[x].l == left && node[x].r == right) { node[x].set = val; node[x].ma = node[x].mi = val; node[x].sum = (right - left + 1) * val; node[x].add = 0; return; } push_down(x); node[x].set = -1; node[x].add = 0; int lx = LL(x); int rx = RR(x); int mid = node[x].l + (node[x].r - node[x].l)/2; if (right <= mid) update_set(left, right, lx, val); else if (left > mid) update_set(left, right, rx, val); else { update_set(left, mid, lx, val); update_set(mid + 1, right, rx, val); } push_up( x); } void update_add(int left, int right, int x, int val) { if (node[x].l == left && node[x].r == right) { node[x].add += val; node[x].ma += val; node[x].mi += val; node[x].sum += (node[x].r - node[x].l + 1) * val; return; } push_down( x); node[x].set = -1; node[x].add = 0; int lx = LL(x); int rx = RR(x); int mid = node[x].l + (node[x].r - node[x].l)/2; if (right <= mid) update_add(left, right, lx, val); else if (left > mid) update_add(left, right, rx, val); else { update_add(left, mid, lx, val); update_add(mid + 1, right, rx, val); } push_up(x); } void query(int left, int right, int x) { if (node[x].l == left && node[x].r == right) { ans_sum += node[x].sum; ans_ma = max( ans_ma, node[x].ma); ans_mi = min( ans_mi, node[x].mi); return; } push_down(x); node[x].set = -1; node[x].add = 0; int mid = node[x].l + (node[x].r - node[x].l)/2; int lx = LL(x); int rx = RR(x); if (right <= mid) query(left, right, lx); else if (left > mid) query(left, right, rx); else { query(left, mid, lx); query(mid + 1, right, rx); } push_up(x); }