大致题意:给你一个r*c的矩阵,r*c<=1e6,给你三种操作,第一种,1 x1 y1 x2 y2 u ,把[x1,y1,x2,y2]子矩阵所有的元素都加上u,第二种,2 x1 y1 x2 y2 u,把[x1,y1,x2,y2]子矩阵的所有元素变成u,第三种,3 x1 y1 x2 y2,查询[x1,y1,x2,y2]所有元素的和,最大值,最小值。
思路:开始并不知道怎么搞,直到发现了r<=20之后,直接暴力好了,反正一个查询或更新的复杂度也就20*log(N)
坑点:是我没想好,第二种操作会对第一种操作有影响,具体就是第二种操作的时候会抵消第一种操作之前所做的状态。所以要处理一下。
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18697
#include <cstdio>
#include <cmath>
#include <iostream>
#define change(x,y) (x-1)*clo+y
#define dist(rt) (t[rt].y - t[rt].x + 1)
using namespace std;
const int MAXN = 1e6+5;
struct Node {
int x,y;
int add,live; //add代表这个区间加上的值,live表示把这个区间所有值变成live;
int minnum,maxnum; //minnum 区间最小,区间最大;
int sum; //区间内总和;
}t[MAXN<<2];
int n,m;
int row,clo;
void Push_Up(int rt) {
t[rt].sum = t[rt<<1].sum + t[rt<<1|1].sum;
t[rt].maxnum = max(t[rt<<1].maxnum,t[rt<<1|1].maxnum);
t[rt].minnum = min(t[rt<<1].minnum,t[rt<<1|1].minnum);
}
void Push_Down(int rt) {
if(t[rt].live) {
t[rt<<1].sum = dist(rt<<1) * t[rt].live;
t[rt<<1|1].sum = dist(rt<<1|1) * t[rt].live;
t[rt<<1].maxnum = t[rt].live; t[rt<<1|1].maxnum = t[rt].live;
t[rt<<1].minnum = t[rt].live; t[rt<<1|1].minnum = t[rt].live;
t[rt<<1].live = t[rt<<1|1].live = t[rt].live;
t[rt<<1].add = t[rt<<1|1].add = 0;//去掉live 对 add的影响,之前add的要全部取消掉
t[rt].live = 0;
}
if(t[rt].add) {
t[rt<<1].sum += dist(rt<<1) * t[rt].add;
t[rt<<1|1].sum += dist(rt<<1|1) * t[rt].add;
t[rt<<1].maxnum += t[rt].add; t[rt<<1|1].maxnum += t[rt].add;
t[rt<<1].minnum += t[rt].add; t[rt<<1|1].minnum += t[rt].add;
t[rt<<1].add += t[rt].add; t[rt<<1|1].add += t[rt].add;
t[rt].add = 0;
}
}
void Build(int x,int y,int rt) {
t[rt].x = x; t[rt].y = y;
t[rt].add = t[rt].live = 0;
if(x == y) {
t[rt].sum = 0;
t[rt].maxnum = 0;
t[rt].minnum = 0;
return ;
}
int mid = (x + y) >> 1;
Build(x,mid,rt<<1);
Build(mid+1,y,rt<<1|1);
Push_Up(rt);
}
void Update(int rt,int left,int right,int u,int flag) {
if(t[rt].x >= left && t[rt].y <= right) {
if(flag) {
t[rt].sum += dist(rt) * u;
t[rt].add += u;
t[rt].maxnum += u;
t[rt].minnum += u;
}
else {
t[rt].sum = dist(rt) * u;
t[rt].live = u;
t[rt].add = 0;//去掉live 对 add的影响,之前add的要全部取消掉
t[rt].maxnum = u;
t[rt].minnum = u;
}
return ;
}
int mid = (t[rt].x + t[rt].y) >> 1;
Push_Down(rt);
if(mid >= left) Update(rt<<1,left,right,u,flag);
if(mid < right) Update(rt<<1|1,left,right,u,flag);
Push_Up(rt);
}
int sum ;
int maxnum , minnum;
void Query(int rt,int left,int right) {
if(t[rt].x >= left && t[rt].y <= right) {
sum += t[rt].sum;
maxnum = max(maxnum,t[rt].maxnum);
minnum = min(minnum,t[rt].minnum);
return ;
}
int mid = (t[rt].x + t[rt].y) >> 1;
Push_Down(rt);
if(mid >= left) Query(rt<<1,left,right);
if(mid < right) Query(rt<<1|1,left,right);
Push_Up(rt);
}
void Print_Tree(int rt) {
static int cnt = 0;
Push_Down(rt);
if(t[rt].x == t[rt].y) {
cnt ++;
if(cnt % 4 == 0) {
printf("%d\n",t[rt].sum);
}
else {
printf("%d ",t[rt].sum);
}
return ;
}
Print_Tree(rt<<1);
Print_Tree(rt<<1|1);
}
void input() {
Build(1,change(row,clo),1);
int ok,u;
int x1,y1,x2,y2;
for(int i = 1 ; i <= n ; i ++) {
//Print_Tree(1);
scanf("%d %d %d %d %d",&ok,&x1,&y1,&x2,&y2);
if(ok == 1) {
scanf("%d",&u); //add
for(int j = x1 ; j <= x2 ; j ++) {
Update(1,change(j,y1),change(j,y2),u,1);
}
}
else if(ok == 2) { //live
scanf("%d",&u);
for(int j = x1 ; j <= x2 ; j ++) {
Update(1,change(j,y1),change(j,y2),u,0);
}
}
else {
sum = 0;
minnum = 0x3f3f3f3f;
maxnum = 0;
for(int j = x1 ; j <= x2 ; j ++) {
Query(1,change(j,y1),change(j,y2));
}
printf("%d %d %d\n",sum,minnum,maxnum);
}
}
}
void solve() {
}
int main(void) {
//freopen("a.in","r",stdin);
while(~scanf("%d %d %d",&row,&clo,&n)) {
input();
solve();
}
}