要建多个线段树,有两个基本操作,set和add,优先级上,set比add高,注意关系;
query里还是要用到pushdown,有pushdown的地方就一定要有maintain,两者有依存关系;
但是pushdown之后,在哪里,在什么位置maintain,不太明白;
写完了,好多错误,,maintain对于子节点和中间节点是有区别的,,query是需要pushdown的;
即便如此还是不可逆转的TLE,超时,结果发现inline很管用啊,一下就到3s多了,过了;
其实超时的原因是p,2*p,2*p+1,应该写成p<<1,p<<1|1,毕竟计算机的位运算比乘法快得多,这样改也可以过;
看到一位同学直接写成了一维数组,就是类似于把二维写成一维,只要1s多一点,没整明白快在哪里。
写出来还是很不容易的。。调试花了差不多2个小时。
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstdio>
using namespace std;
#define RR 22
#define C 3000005
#define INF 1000000000
struct node {
int L,R;
int Sum,Min,Max;
int Set,Add;
node(int sum=0,int c_min=INF,int c_max=0):Sum(sum),Min(c_min),Max(c_max)
{}
};
node st[RR][C];
int main_r, c, m, opr, x1, x2, y1, y2, v;;
void ST_init(int p,int l,int r)
{
for (int row=1;row<=main_r;row++) {
st[row][p].L=l; st[row][p].R=r;
st[row][p].Sum= st[row][p].Max= st[row][p].Min = 0;
st[row][p].Add=0; st[row][p].Set=-1;
}
if (l<r) {
int mid=(l+r)>>1;
ST_init(p<<1,l,mid);
ST_init(p<<1|1,mid+1,r);
}
}
inline void pushdown(int p,int row)
{
if (st[row][p].Set>=0) {
st[row][p<<1].Set = st[row][p<<1|1].Set = st[row][p].Set;
st[row][p<<1].Add = st[row][p<<1|1].Add = st[row][p].Add;
}
else if (st[row][p].Add>0){
st[row][p<<1].Add +=st[row][p].Add;
st[row][p<<1|1].Add +=st[row][p].Add;
}
st[row][p].Set=-1;
st[row][p].Add=0;
}
inline void maintain(int p,int row)
{
if (st[row][p].Set>=0) {
st[row][p].Sum = (st[row][p].R-st[row][p].L+1)*(st[row][p].Set+st[row][p].Add);
st[row][p].Max = st[row][p].Set+st[row][p].Add;
st[row][p].Min = st[row][p].Set+st[row][p].Add;
}
else {
if (st[row][p].L<st[row][p].R) {
st[row][p].Sum = st[row][p<<1].Sum + st[row][p<<1|1].Sum;
st[row][p].Max = max(st[row][p<<1].Max,st[row][p<<1|1].Max);
st[row][p].Min = min(st[row][p<<1].Min,st[row][p<<1|1].Min);
}
else {
st[row][p].Sum = st[row][p].Max = st[row][p].Min = 0;
}
st[row][p].Sum += st[row][p].Add*(st[row][p].R-st[row][p].L+1);
st[row][p].Max += st[row][p].Add;
st[row][p].Min += st[row][p].Add;
}
}
void update(int p,int l,int r,int v,int opr,int row)
{
if (st[row][p].L>=l && st[row][p].R<=r) {
if (opr==1) {
st[row][p].Add+=v;
}
else {
st[row][p].Set=v;
st[row][p].Add=0;
}
}
else {
pushdown(p,row);
int mid=(st[row][p].L+st[row][p].R)/2;
if (l<=mid) update(p<<1,l,r,v,opr,row);
else maintain(p<<1,row);
if (r>mid) update(p<<1|1,l,r,v,opr,row);
else maintain(p<<1|1,row);
}
maintain(p,row);
}
node query(int p,int l,int r,int row)
{
if (st[row][p].Set>=0) {
return node((st[row][p].Set+st[row][p].Add)*(min(st[row][p].R,r)-max(st[row][p].L,l)+1) ,
st[row][p].Set+st[row][p].Add,
st[row][p].Set+st[row][p].Add);
}
else if (st[row][p].L==l && st[row][p].R==r) {
return st[row][p];
}
else {
pushdown(p,row);
maintain(p<<1,row);
maintain(p<<1|1,row);
maintain(p,row);
int mid=(st[row][p].L+st[row][p].R)/2;
node t1,t2;
if (l<=mid)
t1=query(p<<1,l,min(mid,r),row);
if (r>mid)
t2=query(p<<1|1,max(mid+1,l),r,row);
return node(t1.Sum+t2.Sum,
min(t1.Min,t2.Min),
max(t1.Max,t2.Max));
}
}
int main()
{
freopen("1.in","r",stdin);
while (scanf("%d%d%d",&main_r,&c,&m)!=EOF) {
ST_init(1,1,c);
while (m--) {
scanf("%d%d%d%d%d",&opr,&x1,&y1,&x2,&y2);
if (opr<3) {
scanf("%d",&v);
for (int row=x1;row<=x2;row++)
update(1,y1,y2,v,opr,row);
}
else {
node ans;
for (int row=x1;row<=x2;row++) {
node tmp=query(1,y1,y2,row);
ans.Sum += tmp.Sum;
ans.Max = max(ans.Max,tmp.Max);
ans.Min = min(ans.Min,tmp.Min);
}
printf("%d %d %d\n",ans.Sum,ans.Min,ans.Max);
}
}
}
return 0;
}