标签:
题意:给个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行,不妨枚举每一行,去操作。对于一维的线段树,要进行赋值,加法,查询sum,max,min的操作。设两个懒操作变量a,b,a表示赋值的,b表示加法的。当进行赋值操作时,b清0,a+=v;当进行加法操作时,如果a>0,则a+=v,否则b+=v;任何操作时,处理sum,max,min,处理sum时不要忘记乘上区间长度。注意在懒操作和update函数都要进行如上操作。写一个种树、两个更值、三个查询函数。
代码
//Hello. I‘m Peter.
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
return x*f;
}
inline ll readLL(){
ll x=0,f=1;char ch=getchar();
while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
return x*f;
}
int r, c, m;
#define MAXN 1000010
#define lch id<<1
#define rch id<<1|1
#define mid ((l+r)>>1)
struct Segment_Tree{
ll max, min, sum;
ll fu, jia;
int len;
}tree[MAXN << 2];
inline void plant_tree(int id,int l,int r){
tree[id].max = tree[id].min = tree[id].sum = 0;
tree[id].fu = tree[id].jia = 0;
tree[id].len = r - l + 1;
if(l == r) return;
plant_tree(lch, l, mid);
plant_tree(rch, mid + 1, r);
}
void pullup(int id){
tree[id].sum = tree[lch].sum + tree[rch].sum;
tree[id].max = max(tree[lch].max, tree[rch].max);
tree[id].min = min(tree[lch].min, tree[rch].min);
}
void pushdown(int id){
if(tree[id].fu > 0){
tree[lch].fu = tree[id].fu;
tree[lch].jia = 0;
tree[lch].max = tree[lch].min = tree[id].fu;
tree[lch].sum = tree[id].fu * tree[lch].len;
tree[rch].fu = tree[id].fu;
tree[rch].jia = 0;
tree[rch].max = tree[rch].min = tree[id].fu;
tree[rch].sum = tree[id].fu * tree[rch].len;
tree[id].fu = 0;
}
else if(tree[id].jia > 0){
//bug
if(tree[lch].fu > 0) tree[lch].fu += tree[id].jia;
else tree[lch].jia += tree[id].jia;
tree[lch].sum += tree[id].jia * tree[lch].len;
tree[lch].max += tree[id].jia;
tree[lch].min += tree[id].jia;
if(tree[rch].fu > 0) tree[rch].fu += tree[id].jia;
else tree[rch].jia += tree[id].jia;
tree[rch].sum += tree[id].jia * tree[rch].len;
tree[rch].max += tree[id].jia;
tree[rch].min += tree[id].jia;
tree[id].jia = 0;
}
}
inline void update_fu(int id,int ql,int qr,int l,int r,ll v){
if(ql == l && qr == r){
tree[id].fu = v;
tree[id].jia = 0;
tree[id].min = tree[id].max = v;
tree[id].sum = v * tree[id].len;
return;
}
pushdown(id);
if(qr <= mid) update_fu(lch, ql, qr, l, mid, v);
else if(mid < ql) update_fu(rch, ql, qr, mid + 1, r, v);
else update_fu(lch, ql, mid, l, mid, v), update_fu(rch, mid + 1, qr, mid + 1, r, v);
pullup(id);
}
inline void update_jia(int id,int ql,int qr,int l,int r,ll v){
if(ql == l && qr == r){
if(tree[id].fu > 0) tree[id].fu += v;
else tree[id].jia += v;
tree[id].sum += v * tree[id].len;
tree[id].max += v;
tree[id].min += v;
return;
}
pushdown(id);
if(qr <= mid) update_jia(lch, ql, qr, l, mid, v);
else if(mid < ql) update_jia(rch, ql, qr, mid + 1, r, v);
else update_jia(lch, ql, mid, l, mid, v), update_jia(rch, mid + 1, qr, mid + 1, r, v);
pullup(id);
}
inline ll query_min(int id,int ql,int qr,int l,int r){
if(ql == l && qr == r) return tree[id].min;
pushdown(id);
if(qr <= mid) return query_min(lch, ql, qr, l, mid);
else if(mid < ql) return query_min(rch, ql, qr, mid + 1, r);
else return min(query_min(lch, ql, mid, l, mid), query_min(rch, mid + 1, qr, mid + 1, r));
}
inline ll query_max(int id,int ql,int qr,int l,int r){
if(ql == l && qr == r) return tree[id].max;
pushdown(id);
if(qr <= mid) return query_max(lch, ql, qr, l, mid);
else if(mid < ql) return query_max(rch, ql, qr, mid + 1, r);
else return max(query_max(lch, ql, mid, l, mid), query_max(rch, mid + 1, qr, mid + 1, r));
}
inline ll query_sum(int id,int ql,int qr,int l,int r){
if(ql == l && qr == r) return tree[id].sum;
pushdown(id);
if(qr <= mid) return query_sum(lch, ql, qr, l, mid);
else if(mid < ql) return query_sum(rch, ql, qr, mid + 1, r);
else return query_sum(lch, ql, mid, l, mid) + query_sum(rch, mid + 1, qr, mid + 1, r);
}
int f(int x,int y){
return (x - 1) * c + y;
}
int main(){
//freopen("/Users/peteryuanpan/data.txt","r",stdin);
while(~scanf("%d%d%d",&r,&c,&m)){
int n = r * c;
plant_tree(1, 1, n);
for(int im = 1; im <= m; im++){
int ty = read();
int x1, y1, x2, y2;
ll v;
if(ty == 1){
x1 = read(), y1 = read();
x2 = read(), y2 = read();
v = readLL();
for(int i = x1; i <= x2; i++){
int l = f(i, y1), r = f(i, y2);
update_jia(1, l, r, 1, n, v);
}
}
else if(ty == 2){
x1 = read(), y1 = read();
x2 = read(), y2 = read();
v = readLL();
for(int i = x1; i <= x2; i++){
int l = f(i, y1), r = f(i, y2);
update_fu(1, l, r, 1, n, v);
}
}
else if(ty == 3){
ll sum = 0, maxi = -1e18, mini = 1e18;
x1 = read(), y1 = read();
x2 = read(), y2 = read();
for(int i = x1; i <= x2; i++){
int l = f(i, y1), r = f(i, y2);
sum += query_sum(1, l, r, 1, n);
maxi = max(maxi, query_max(1, l, r, 1, n));
mini = min(mini, query_min(1, l, r, 1, n));
//printf("i = %d l=%d r=%d %lld %lld %lld\n",i,l,r,sum,mini,maxi);
}
printf("%lld %lld %lld\n",sum,mini,maxi);
}
}
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
UVa 11992 Fast Matrix Operations(线段树双懒操作,二维转一维)
标签:
原文地址:http://blog.csdn.net/uestc_peterpan/article/details/47112043