UVA 11992 Fast Matrix Operations (二维线段树)

时间:2023-03-08 15:45:07

解法:因为至多20行,所以至多建20棵线段树,每行建一个。具体实现如下,有些复杂,慢慢看吧。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 1000010 struct node
{
int mini,maxi,sum;
int addmark,setmark;
}tree[][*N]; int i; void pushup(int i,int rt)
{
tree[i][rt].sum = tree[i][*rt].sum + tree[i][*rt+].sum;
tree[i][rt].mini = min(tree[i][*rt].mini,tree[i][*rt+].mini);
tree[i][rt].maxi = max(tree[i][*rt].maxi,tree[i][*rt+].maxi);
} void build(int i,int l,int r,int rt)
{
tree[i][rt].sum = tree[i][rt].mini = tree[i][rt].maxi = ;
tree[i][rt].setmark = -;
tree[i][rt].addmark = ;
if(l == r)
return;
int mid = (l+r)/;
build(i,l,mid,*rt);
build(i,mid+,r,*rt+);
pushup(i,rt);
} void pushdown(int i,int l,int r,int rt)
{
if(tree[i][rt].setmark == - && tree[i][rt].addmark == )
return;
int mid = (l+r)/;
if(tree[i][rt].setmark >= )
{
tree[i][*rt].sum = tree[i][rt].setmark*(mid-l+);
tree[i][*rt+].sum = tree[i][rt].setmark*(r-mid);
tree[i][*rt].mini = tree[i][*rt+].mini = tree[i][rt].setmark; //
tree[i][*rt].maxi = tree[i][*rt+].maxi = tree[i][rt].setmark; //
tree[i][*rt].addmark = tree[i][*rt+].addmark = ; //
tree[i][*rt].setmark = tree[i][*rt+].setmark = tree[i][rt].setmark;
tree[i][rt].setmark = -;
}
if(tree[i][rt].addmark > )
{
tree[i][*rt].sum += tree[i][rt].addmark*(mid-l+);
tree[i][*rt+].sum += tree[i][rt].addmark*(r-mid);
tree[i][*rt].maxi += tree[i][rt].addmark; //
tree[i][*rt].mini += tree[i][rt].addmark;
tree[i][*rt+].maxi += tree[i][rt].addmark;
tree[i][*rt+].mini += tree[i][rt].addmark; //
tree[i][*rt].addmark += tree[i][rt].addmark;
tree[i][*rt+].addmark += tree[i][rt].addmark;
tree[i][rt].addmark = ;
}
} void add(int l,int r,int aa,int bb,int val,int rt)
{
if(aa>r||bb<l)
return;
if(aa<=l&&bb>=r)
{
tree[i][rt].addmark += val;
//tree[i][rt].setmark = -1;
tree[i][rt].sum += (r-l+)*val;
tree[i][rt].maxi += val;
tree[i][rt].mini += val;
return;
}
pushdown(i,l,r,rt);
int mid = (l+r)/;
if(aa<=mid)
add(l,mid,aa,bb,val,*rt);
if(bb>mid)
add(mid+,r,aa,bb,val,*rt+);
pushup(i,rt);
} void setval(int l,int r,int aa,int bb,int val,int rt)
{
if(aa>r||bb<l)
return;
if(aa<=l&&bb>=r)
{
tree[i][rt].setmark = val;
tree[i][rt].addmark = ;
tree[i][rt].sum = val*(r-l+);
tree[i][rt].maxi = tree[i][rt].mini = val;
return;
}
pushdown(i,l,r,rt);
int mid = (l+r)/;
if(aa<=mid)
setval(l,mid,aa,bb,val,*rt);
if(bb>mid)
setval(mid+,r,aa,bb,val,*rt+);
pushup(i,rt);
} struct node_ans
{
int sum;
int mini,maxi;
}; node_ans query(int l,int r,int aa,int bb,int rt)
{
node_ans res,ka1,ka2;
if(aa<=l && bb>=r)
{
res.sum = tree[i][rt].sum;
res.maxi = tree[i][rt].maxi;
res.mini = tree[i][rt].mini;
return res;
}
pushdown(i,l,r,rt);
int mid = (l+r)/;
if(bb<=mid)
return query(l,mid,aa,bb,*rt);
else if(aa>mid)
return query(mid+,r,aa,bb,*rt+);
else
{
ka1 = query(l,mid,aa,bb,*rt);
ka2 = query(mid+,r,aa,bb,*rt+);
res.sum = ka1.sum + ka2.sum;
res.maxi = max(ka1.maxi,ka2.maxi);
res.mini = min(ka1.mini,ka2.mini);
return res;
}
} int main()
{
int r,c,m;
int k,zuo;
int x1,y1,x2,y2,val;
int sum,mmax,mmin;
while(scanf("%d%d%d",&r,&c,&m)!=EOF)
{
for(i=;i<=r;i++)
{
build(i,,c,);
}
for(k=;k<m;k++)
{
scanf("%d",&zuo);
if(zuo == )
{
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&val);
for(i=x1;i<=x2;i++)
{
add(,c,y1,y2,val,);
}
}
else if(zuo == )
{
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&val);
for(i=x1;i<=x2;i++)
{
setval(,c,y1,y2,val,);
}
}
else
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
node_ans la;
sum = ;
mmax = -Mod;
mmin = Mod;
for(i=x1;i<=x2;i++)
{
la = query(,c,y1,y2,);
sum += la.sum;
mmax = max(mmax,la.maxi);
mmin = min(mmin,la.mini);
}
printf("%d %d %d\n",sum,mmin,mmax);
}
}
}
}