这题我不太会写,主要参考这篇博客:
bzoj1513 [POI2006]Tet-Tetris 3D(二维线段树)
这种结构很值得学习
题目大意:
在一个给定的矩形区域内,每次查询一个矩形的最大值,然后再把这个矩形内的值全都赋成这个值加上一个数,问最后的最大值是多少
我们需要维护两个标记:A标记和B标记
A标记在修改的时候精确覆盖到线段树上的每个对应节点上,查询的时候精准定位
B标记记录的是线段树一条链上的标记,标记永久化
A标记是精准标记,B标记是标记永久化的产物
但是在查询的时候,因为是标记永久化,所以B标记反而是准确的,但是我们也不能忽略A标记(顺带便就查询了吧)
#define ls i<<1
#define rs i<<1|1
#define mid ((l+r)>>1)
#define lson ls,l,mid
#define rson rs,mid+1,r
const int maxn=4e3+7;
int D,S,n,xl,xr,yl,yr;
struct nodey{
int a[maxn],b[maxn];
void update(int i,int l,int r,int x,int y,int k){
if(l>y||r<x) return;
b[i]=max(b[i],k);
if(x<=l&&r<=y){
a[i]=max(a[i],k);
return;
}
update(lson,x,y,k); update(rson,x,y,k);
}
int query(int i,int l,int r,int x,int y){
if(l>y||r<x) return 0;
if(x<=l&&r<=y) return b[i];
int ans=a[i];
ans=max(ans,query(lson,x,y));
ans=max(ans,query(rson,x,y));
return ans;
}
};
struct nodex{
nodey a[maxn],b[maxn];
void update(int i,int l,int r,int x,int y,int k){
if(l>y||r<x) return;
b[i].update(1,1,S,yl,yr,k);
if(x<=l&&r<=y){
a[i].update(1,1,S,yl,yr,k);
return;
}
update(lson,x,y,k); update(rson,x,y,k);
}
int query(int i,int l,int r,int x,int y){
if(l>y||r<x) return 0;
if(x<=l&&r<=y) return b[i].query(1,1,S,yl,yr);
int ans=a[i].query(1,1,S,yl,yr);
ans=max(ans,query(lson,x,y));
ans=max(ans,query(rson,x,y));
return ans;
}
};
nodex T;
int main(){
D=read(); S=read(); n=read();
for(int i=1;i<=n;i++){
int d,s,w,x,y; d=read(); s=read(); w=read(); x=read(); y=read();
xl=x+1; yl=y+1; xr=x+d; yr=x+s;
int temp=T.query(1,1,D,xl,xr);
T.update(1,1,D,xl,xr,temp+w);
}
yl=1; yr=S;
printf("%d",T.query(1,1,D,1,D));
}