数据范围很大,但是可以每行建一个线段树,化为线性的
set的优先级高于add
pushdown的时候相当于在add和sett中对一个整个的区间进行“赋值”一样,所以还要加上改sum,min1,max1的部分
三个询问可以一起做。。。
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; #define MAXN 4000000 //#define INF 1000000000 //每一行建一颗线段树,只要开总元素个数的数组即可,下标可以算出 int ll,rr,r,c,m,ans1,ans2,ans3,op,x1,y1,x2,y2,v; struct point{ int l,r,sum,max1,min1; }tree[MAXN]; int addv[MAXN],setv[MAXN];//lazy_tag void build(int p,int l,int r) { tree[p].l=l; tree[p].r=r; tree[p].sum=0; tree[p].min1=0; tree[p].max1=0; if (l==r) return ; int mid=(l+r) >> 1; build(p<<1,l,mid); build(p<<1^1,mid+1,r); return ; } //优先级 set>add(当set>=0 add>0时) void pushdown(int p) { if (setv[p]>=0) { setv[p<<1]=setv[p<<1^1]=setv[p]; addv[p<<1]=addv[p<<1^1]=0; tree[p<<1].sum=(tree[p<<1].r-tree[p<<1].l+1)*setv[p]; tree[p<<1^1].sum=(tree[p<<1^1].r-tree[p<<1^1].l+1)*setv[p]; tree[p<<1].min1=tree[p<<1^1].min1=setv[p]; tree[p<<1].max1=tree[p<<1^1].max1=setv[p]; setv[p]=-1;//放最后!! } if (addv[p]>0) { addv[p<<1]+=addv[p]; addv[p<<1^1]+=addv[p]; tree[p<<1].sum+=(tree[p<<1].r-tree[p<<1].l+1)*addv[p]; tree[p<<1^1].sum+=(tree[p<<1^1].r-tree[p<<1^1].l+1)*addv[p]; tree[p<<1].min1+=addv[p]; tree[p<<1].max1+=addv[p]; tree[p<<1^1].min1+=addv[p]; tree[p<<1^1].max1+=addv[p]; addv[p]=0; } } void updata(int p) { tree[p].min1=min(tree[p<<1].min1,tree[p<<1^1].min1); tree[p].max1=max(tree[p<<1].max1,tree[p<<1^1].max1); tree[p].sum=tree[p<<1].sum+tree[p<<1^1].sum; } void add(int p,int l,int r,int v) { if (tree[p].l==l && tree[p].r==r) { addv[p]+=v; tree[p].sum+=(r-l+1)*v;//if的同时维护 tree[p].min1+=v; tree[p].max1+=v; return ; } pushdown(p);//pushdown要在这里用,因为之前if中的已经是可以直接判断的了 //要向下走再下传标记 int mid=(tree[p].l+tree[p].r) >> 1; if (r<=mid) add(p<<1,l,r,v); if (l>mid) add(p<<1^1,l,r,v); if (l<=mid && r>mid) { add(p<<1,l,mid,v); add(p<<1^1,mid+1,r,v); } updata(p); } void sett(int p,int l,int r,int v) { if (tree[p].l==l && tree[p].r==r) { setv[p]=v; addv[p]=0;//这个一开始也没加 tree[p].sum=(r-l+1)*v; tree[p].min1=v; tree[p].max1=v; return ; } pushdown(p); int mid=(tree[p].l+tree[p].r) >> 1; if (r<=mid) sett(p<<1,l,r,v); if (l>mid) sett(p<<1^1,l,r,v); if (l<=mid && r>mid) { sett(p<<1,l,mid,v); sett(p<<1^1,mid+1,r,v); } updata(p); } void query(int p,int l,int r) { if (tree[p].l==l && tree[p].r==r) { ans1+=tree[p].sum; ans2=min(ans2,tree[p].min1); ans3=max(ans3,tree[p].max1); return ; } pushdown(p); int mid=(tree[p].l+tree[p].r) >> 1; if (r<=mid) query(p<<1,l,r); if (l>mid) query(p<<1^1,l,r); if (l<=mid && r>mid) { query(p<<1,l,mid); query(p<<1^1,mid+1,r); } updata(p); } int main() { while (cin>>r>>c>>m) { memset(addv,0,sizeof(addv)); memset(setv,-1,sizeof(setv));//因为可能set为0 build(1,1,r*c); for (int i=1;i<=m;i++) { cin>>op>>x1>>y1>>x2>>y2; if (op==1) { cin>>v; for (int j=x1;j<=x2;j++) { add(1,(j-1)*c+y1,(j-1)*c+y2,v); } } if (op==2) { cin>>v; for (int j=x1;j<=x2;j++) { sett(1,(j-1)*c+y1,(j-1)*c+y2,v); } } if (op==3) { ans2=1000000000; ans1=ans3=0; for (int j=x1;j<=x2;j++) { ll=(j-1)*c+y1; rr=(j-1)*c+y2; query(1,ll,rr); } cout<<ans1<<' '<<ans2<<' '<<ans3<<endl; } } } return 0; }