BZOJ1513: [POI2006]Tet-Tetris 3D

来源:互联网 发布:淘宝旺旺名是什么意思 编辑:程序博客网 时间:2024/05/22 10:54
题目大意:在一个给定的矩形区域内,每次查询一个矩形的最大值,然后再把这个矩形内的值全都赋成这个值加上一个数,问最后的最大值是多少

学了二维线段树,以前以为二维线段树只是树套树,后来发现二维线段树必须标记永久化
标记永久化对于线段树上每个节点需要维护两个量,拿维护最大值来举例,你需要维护一个值have,代表这个子树里有这样一个最大值,另外一个值all代表这个子树里全都是这个值
那么赋值的时候我们需要把路径上的have全部更新并更新对应区间的all
查询的时候我们要用路径上所有的all和对应区间的have来更新答案

嗯,然后就没什么了,注意更新的时候一定要取max,不要以为这道题单调就可以直接赋值,这是错的!具体为什么可以自己想一想(其实是我说不明白)

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define N 1010#define M 3using namespace std;int D,S;struct INSSEG{int all[N*M],hav[N*M];void change(int now,int l,int r,int ll,int rr,int v){hav[now]=max(hav[now],v);if(ll==l&&rr==r){all[now]=max(v,all[now]);return;}int mid=(l+r)>>1;if(rr<=mid) change(now<<1,l,mid,ll,rr,v);else if(ll>mid) change(now<<1|1,mid+1,r,ll,rr,v);else change(now<<1,l,mid,ll,mid,v),change(now<<1|1,mid+1,r,mid+1,rr,v);}int check(int now,int l,int r,int ll,int rr){if(ll==l&&rr==r) return hav[now];int ret=all[now];int mid=(l+r)>>1;if(rr<=mid) ret=max(ret,check(now<<1,l,mid,ll,rr));else if(ll>mid) ret=max(ret,check(now<<1|1,mid+1,r,ll,rr));else ret=max(ret,max(check(now<<1,l,mid,ll,mid),check(now<<1|1,mid+1,r,mid+1,rr)));return ret;}};struct OUSSEG{INSSEG all[N*M],hav[N*M];void change(int now,int l,int r,int ll,int rr,int lll,int rrr,int v){hav[now].change(1,0,S,lll,rrr,v);if(ll<=l&&rr>=r){all[now].change(1,0,S,lll,rrr,v);return;}int mid=(l+r)>>1;if(rr<=mid) change(now<<1,l,mid,ll,rr,lll,rrr,v);else if(ll>mid) change(now<<1|1,mid+1,r,ll,rr,lll,rrr,v);else change(now<<1,l,mid,ll,mid,lll,rrr,v),change(now<<1|1,mid+1,r,mid+1,rr,lll,rrr,v);}int check(int now,int l,int r,int ll,int rr,int lll,int rrr){if(ll<=l&&rr>=r) return hav[now].check(1,0,S,lll,rrr);int ret=all[now].check(1,0,S,lll,rrr);int mid=(l+r)>>1;if(rr<=mid) ret=max(ret,check(now<<1,l,mid,ll,rr,lll,rrr));else if(ll>mid) ret=max(ret,check(now<<1|1,mid+1,r,ll,rr,lll,rrr));else ret=max(ret,max(check(now<<1,l,mid,ll,mid,lll,rrr),check(now<<1|1,mid+1,r,mid+1,rr,lll,rrr)));return ret;}}O;int main(){int n;scanf("%d%d%d",&D,&S,&n);int d,s,w,x,y;while(n--){scanf("%d%d%d%d%d",&d,&s,&w,&x,&y);int most=O.check(1,0,D,x+1,x+d,y+1,y+s);O.change(1,0,D,x+1,x+d,y+1,y+s,most+w);}printf("%d",O.check(1,0,D,0,D,0,S));}

0 0