题意:给定一个空矩阵,对其进行两种操作:
1.矩阵询问max
2.矩阵赋值
你只需要输出最后的矩阵最大值。
二维线段树……应该是显然的,但是做的时候发现自己Naive了……
首先我们在修改一个子矩阵时,包含子矩阵的那些矩阵的值在外层没办法上传。
其次我们发现子矩阵的子矩阵也没有信息……
忽然想到标记永久化这个东西,想到一种方法大概这样:
比较显然的一点就是,内外层线段树是等效的,所以我们只要不在外层上传信息,下传信息,就”不必“在内层下传信息。
1.在每层线段树我们记录两个值,一个值是完美覆盖该区间的标记Tag,一个值是子树最大值Mx。
我们在修改的时候,可以这样做:
对于外层线段树上的那条修改路径,由于其修改是单增不降的,所以我们可以直接更改那条路径上的Mx,直到修改到某个节点,它被这个修改区间覆盖,这时候我们不仅要修改子树的值,还需要修改它的Tag。
所以,对于修改,我们只需要对于每层的线段树沿途也进行修改即可。
2.对于查询最大值:
我们在查询某个子矩阵的最大值的时候,在路径上显然要查询所有路径上的Tag,对于某个被询问区间覆盖的区间,我们需要查询它的子树值,最后对所有值取max。
特别注意,如果没有特别的数据弱,我们里层需要动态开点。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#define Rep(i,n) for(int i = 1; i <= n ; i ++)
#define RepG(i,x) for(int i = head[x] ;~ i ; i = edge[i].next)
#define Rep_d(i,n) for(int i = n ; i > 0 ; i --)
#define Rep_0(i,n) for(int i = 0 ; i < n ; i ++)
#define RD(i,x,n) for(int i = x; i <= n ; i ++)
#define CLR(a,b) memset(a,b,sizeof(a))
#define RDD(i,x,n) for(int i = x; i >= n; i --)
#define u t[x]
#define lc ch[0]
#define rc ch[1]
#define v edge[i].to
#define ulfc t[u.lc]
#define urtc t[u.rc]
using namespace std;
const int inf = 1 << 30;
typedef long long ll;
int read(){
char ch = getchar();
while((ch < '0' || ch > '9') && ch != '-')ch = getchar ();
int x = 0;
bool flag = 0;
if(ch == '-')ch = getchar(),flag = 1;
while(ch >= '0' && ch <= '9')x = (x << 1) + (x << 3) + ch - '0',ch = getchar ();
return flag ? -x : x;
}
const int N = 1005;
int n,m,k;
#define lson x << 1,l,mid,ql,qr
#define rson x << 1 | 1,mid + 1,r,ql,qr
#define RT 1,1,n,ql,qr
int Ql,Qr;
struct Seg{
struct Tree{
int Mx[N * 3],tag[N * 3];
void Modify(int x,int l,int r,int ql,int qr,int s){
Mx[x] = max(Mx[x],s);
if(l >= ql && r <= qr){
tag[x] = max(s,tag[x]);
return ;
}
int mid = l + r >> 1;
if(ql <= mid)Modify(lson,s);
if(mid < qr)Modify(rson,s);
}
int Qry(int x,int l,int r,int ql,int qr){
if(l >= ql && r <= qr)return Mx[x];
int ans = tag[x],mid = l + r >> 1;
if(ql <= mid)ans = max(Qry(lson),ans);
if(mid < qr)ans = max(Qry(rson),ans);
return ans;
}
};
Tree Mx[N * 3],tag[N * 3];
void Modify(int x,int l,int r,int ql,int qr,int s){
Mx[x].Modify(RT,s);
if(l >= Ql && r <= Qr){
tag[x].Modify(RT,s);
return ;
}
int mid = l + r >> 1;
if(Ql <= mid)Modify(lson,s);
if(mid < Qr)Modify(rson,s);
}
int Qry(int x,int l,int r,int ql,int qr){
if(l >= Ql && r <= Qr)
return Mx[x].Qry(RT);
int ans = tag[x].Qry(RT),mid = l + r >> 1;
if(Ql <= mid)ans = max(ans,Qry(lson));
if(mid < Qr)ans = max(ans,Qry(rson));
return ans;
}
}seg;
int main (){
n = read(),m = read(),k = read();
Rep(i,k)
{
int len,wd,ht,x,y;
len = read(),wd = read(),ht = read(),x = read(),y = read();
Ql = x + 1;
Qr = x + len;
int p;
p = seg.Qry(1,1,n,y + 1,y + wd);
seg.Modify(1,1,n,y + 1,y + wd,p + ht);
}
Ql = 1,Qr = n;
printf("%d\n",seg.Qry(1,1,n,1,n));
return 0;
}
/* 7 5 4 4 3 2 0 0 3 3 1 3 0 7 1 2 0 3 2 3 3 2 2 */