[BZOJ1513]Tet-Tetris 3D
阿新 • • 發佈:2018-02-17
modify 不用 最大值 d+ 線段 can tdi printf include
get了新的標記永久化技能~
這題要求詢問max和覆蓋,因為是線段樹套線段樹,所以內外都不可以標記下傳
這種標記永久化的套路是維護兩個標記:$mx,all$,$mx$表示這個子樹內的真最大值,$all$表示整個子樹曾經被覆蓋過這樣的最大值
修改:更新經過節點的$mx$和覆蓋區間節點的$all$
查詢:統計經過節點的$all$和覆蓋區間節點的$mx$
然後就不用下傳標記了,還有寫成struct會方便許多
類似地,區間加的標記永久化的兩個標記是【子樹和(假)】還有【子樹增值】,【子樹和(假)】+【子樹增值】=【子樹和(真)】
#include<stdio.h> int n,m; int max(int a,int b){return a>b?a:b;} struct iseg{ int mx[3010],al[3010]; int query(int L,int R,int l,int r,int x){ if(L<=l&&r<=R)return mx[x]; int ans=al[x],mid=(l+r)>>1; if(L<=mid)ans=max(ans,query(L,R,l,mid,x<<1)); if(mid<R)ans=max(ans,query(L,R,mid+1,r,x<<1|1)); return ans; } void modify(int L,int R,int v,int l,int r,int x){ mx[x]=max(mx[x],v); if(L<=l&&r<=R){ al[x]=max(al[x],v); return; } int mid=(l+r)>>1; if(L<=mid)modify(L,R,v,l,mid,x<<1); if(mid<R)modify(L,R,v,mid+1,r,x<<1|1); } }; struct oseg{ iseg mx[3010],al[3010]; int query(int L,int R,int Li,int Ri,int l,int r,int x){ if(L<=l&&r<=R)return mx[x].query(Li,Ri,1,m,1); int ans=al[x].query(Li,Ri,1,m,1),mid=(l+r)>>1; if(L<=mid)ans=max(ans,query(L,R,Li,Ri,l,mid,x<<1)); if(mid<R)ans=max(ans,query(L,R,Li,Ri,mid+1,r,x<<1|1)); return ans; } void modify(int L,int R,int Li,int Ri,int v,int l,int r,int x){ mx[x].modify(Li,Ri,v,1,m,1); if(L<=l&&r<=R)return al[x].modify(Li,Ri,v,1,m,1); int mid=(l+r)>>1; if(L<=mid)modify(L,R,Li,Ri,v,l,mid,x<<1); if(mid<R)modify(L,R,Li,Ri,v,mid+1,r,x<<1|1); } }t; int main(){ int q,d,s,w,x,y; scanf("%d%d%d",&n,&m,&q); while(q--){ scanf("%d%d%d%d%d",&d,&s,&w,&x,&y); t.modify(x+1,x+d,y+1,y+s,t.query(x+1,x+d,y+1,y+s,1,n,1)+w,1,n,1); } printf("%d",t.query(1,n,1,m,1,n,1)); }
[BZOJ1513]Tet-Tetris 3D