题目描述
给定一个r*c(r<=20,r*c<=1e6)的矩阵,其元素都是0,现在对其子矩阵进行操作。
1 x1 y1 x2 y2 val 表示将(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素加val;
2 x1 y1 x2 y2 val 表示将(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素变为val;
3 x1 y1 x2 y2 val 表示输出(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素的和,最小值和最大值。
共有m次操作(1<=m<=20000)
输入
有多组数据。每组数据第一行有3个整数r,c,m ,接下来m行,每行一个操作。
输出
对于每个操作3,输出三个数表示答案。
样例输入
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
题解
开20棵线段树,然后普通操作操作就ok。
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long #define inf 1e9+5 const int maxn=1e5+5; struct SegmentTree{ int v,s_max,s_min,l,r,add,sett; }st[25][maxn*4]; int tot,tot_min,tot_max; template<typename T>void read(T& aa) { char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } void pushup(int root,int op){ st[op][root].v=st[op][root*2].v+st[op][root*2+1].v; st[op][root].s_max=max(st[op][root*2].s_max,st[op][root*2+1].s_max); st[op][root].s_min=min(st[op][root*2].s_min,st[op][root*2+1].s_min); } void build(int root,int l,int r,int op){ st[op][root].l=l; st[op][root].r=r; st[op][root].sett=-1; if(l==r){ st[op][root].v=0; st[op][root].s_max=0; st[op][root].s_min=0; } else{ int m=(l+r)>>1; build(root*2,l,m,op); build(root*2+1,m+1,r,op); pushup(root,op); } } void pushdown(int root,int op){ if(st[op][root].sett>=0){ st[op][root*2].sett=st[op][root*2+1].sett=st[op][root].sett; st[op][root*2].s_max=st[op][root*2+1].s_max=st[op][root*2].s_min=st[op][root*2+1].s_min=st[op][root].sett; st[op][root*2].v=st[op][root].sett*(st[op][root*2].r-st[op][root*2].l+1); st[op][root*2+1].v=st[op][root].sett*(st[op][root*2+1].r-st[op][root*2+1].l+1); st[op][root].sett=-1;st[op][root*2].add=st[op][root*2+1].add=0; } if(st[op][root].add>0){ st[op][root*2].add+=st[op][root].add; st[op][root*2+1].add+=st[op][root].add; st[op][root*2].v+=st[op][root].add*(st[op][root*2].r-st[op][root*2].l+1); st[op][root*2+1].v+=st[op][root].add*(st[op][root*2+1].r-st[op][root*2+1].l+1); st[op][root*2].s_max+=st[op][root].add; st[op][root*2+1].s_max+=st[op][root].add; st[op][root*2].s_min+=st[op][root].add; st[op][root*2+1].s_min+=st[op][root].add; st[op][root].add=0; } } void add(int root,int l,int r,int val,int op){ if(st[op][root].l>r||st[op][root].r<l) return ; if(st[op][root].l>=l&&st[op][root].r<=r){ st[op][root].add+=val; st[op][root].v+=val*(st[op][root].r-st[op][root].l+1); st[op][root].s_max+=val; st[op][root].s_min+=val; } else{ pushdown(root,op); add(root*2,l,r,val,op); add(root*2+1,l,r,val,op); pushup(root,op); } } void change(int root,int l,int r,int val,int op){ if(st[op][root].l>r||st[op][root].r<l) return ; if(st[op][root].l>=l&&st[op][root].r<=r){ st[op][root].v=val*(st[op][root].r-st[op][root].l+1); st[op][root].sett=val; st[op][root].s_max=st[op][root].s_min=val; st[op][root].add=0; } else{ pushdown(root,op); change(root*2,l,r,val,op); change(root*2+1,l,r,val,op); pushup(root,op); } } int query_sum(int root,int l,int r,int op){ if(st[op][root].l>r||st[op][root].r<l) return 0; if(st[op][root].l>=l&&st[op][root].r<=r) return st[op][root].v; else{ pushdown(root,op); return query_sum(root*2,l,r,op)+query_sum(root*2+1,l,r,op); } } int query_min(int root,int l,int r,int op){ if(st[op][root].l>r||st[op][root].r<l) return inf; if(st[op][root].l>=l&&st[op][root].r<=r) return st[op][root].s_min; else{ pushdown(root,op); return min(query_min(root*2,l,r,op),query_min(root*2+1,l,r,op)); } } int query_max(int root,int l,int r,int op){ if(st[op][root].l>r||st[op][root].r<l) return 0; if(st[op][root].l>=l&&st[op][root].r<=r) return st[op][root].s_max; else{ pushdown(root,op); return max(query_max(root*2,l,r,op),query_max(root*2+1,l,r,op)); } } int main(){ int r,c,m,opt,x1,x2,y1,y2,v; while(scanf("%d",&r)!=EOF){ read(c),read(m); memset(st,0,sizeof(st)); for(int i=1;i<=r;i++) build(1,1,c,i); while(m--){ read(opt),read(x1),read(y1),read(x2),read(y2); if(opt==1){ read(v); for(int i=x1;i<=x2;i++) add(1,y1,y2,v,i); } else if(opt==2){ read(v); for(int i=x1;i<=x2;i++) change(1,y1,y2,v,i); } else{ tot_min=inf,tot_max=0,tot=0; for(int i=x1;i<=x2;i++){ tot+=query_sum(1,y1,y2,i); tot_min=min(tot_min,query_min(1,y1,y2,i)); tot_max=max(tot_max,query_max(1,y1,y2,i)); } printf("%d %d %d ",tot,tot_min,tot_max); } } } return 0; }