BZOJ1513
我們經常提及的二維線段樹有兩種寫法,一種是四分樹,一種是樹套樹,寫成四分樹的都是神仙。
樹套樹寫法還是比較好理解的,不過要是讓自己硬套的話可能很不容易套出來的
這里的二維線段樹,外層線段樹是對方陣的正投影,而內層線段樹是對方陣的側投影
這里的內層線段樹可以變換成一棵普通的帶lazy tag的線段樹,外層的應該很難吧
然后,介紹一下怎么寫:
int D,S,N,ql,qr,qd,qu;
D是矩陣長,S是矩陣寬,N是修改(修改內嵌查詢)的次數,然后ql,qr,qd,qu表示每一次修改區間的四個端點
我們看內層線段樹,內層線段樹其實就是維護了一個最值
struct segx { int v[3005],tag[3005]; void change(int k,int l,int r,int x,int y,int val) { v[k]=max(v[k],val); if(l==x&&y==r) {tag[k]=max(tag[k],val);return;} int mid=(l+r)>>1; if(x<=mid) change(k<<1,l,mid,x,min(mid,y),val); if(y>mid) change(k<<1|1,mid+1,r,max(x,mid+1),y,val); } int query(int k,int l,int r,int x,int y) { if(l==x&&y==r) return v[k]; int mid=(l+r)>>1,ans=tag[k]; if(x<=mid) ans=max(ans,query(k<<1,l,mid,x,min(mid,y))); if(y>mid) ans=max(ans,query(k<<1|1,mid+1,r,max(x,mid+1),y)); return ans;
如果不是追求極限的做法,直接這樣就可以了了,沒必要加上lazytag,因為那樣應該不是題目重點(除非是出題人,有腦洞。。)
然后是外層線段樹,這里的銜接還是比較自然地,不像別的樹套樹,可以這么形容一下,別的樹套樹銜接都是帶鋸齒的,這里是平滑的
struct segy { segx v[3005],tag[3005]; void change(int k,int l,int r,int x,int y,int val) { v[k].change(1,1,S,qd,qu,val); if(l==x&&y==r) {tag[k].change(1,1,S,qd,qu,val);return;} int mid=(l+r)>>1; if(x<=mid) change(k<<1,l,mid,x,min(mid,y),val); if(y>mid) change(k<<1|1,mid+1,r,max(x,mid+1),y,val); } int query(int k,int l,int r,int x,int y) { if(l==x&&y==r) return v[k].query(1,1,S,qd,qu); int mid=(l+r)>>1,ans=tag[k].query(1,1,S,qd,qu); if(x<=mid) ans=max(ans,query(k<<1,l,mid,x,min(mid,y))); if(y>mid) ans=max(ans,query(k<<1|1,mid+1,r,max(x,mid+1),y)); return ans; } }T;
我們可以看到內外還是比較協調統一的,最后給出完整實現:
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 int D,S,N,ql,qr,qd,qu; 5 long long read() 6 { 7 long long x=0,f=1;char ch=getchar(); 8 while(ch<'0'||ch>'9') {if(ch=='-')f=-1; ch=getchar();} 9 while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} 10 return x*f; 11 } 12 struct segx 13 { 14 int v[3005],tag[3005]; 15 void change(int k,int l,int r,int x,int y,int val) 16 { 17 v[k]=max(v[k],val); 18 if(l==x&&y==r) {tag[k]=max(tag[k],val);return;} 19 int mid=(l+r)>>1; 20 if(x<=mid) change(k<<1,l,mid,x,min(mid,y),val); 21 if(y>mid) change(k<<1|1,mid+1,r,max(x,mid+1),y,val); 22 } 23 int query(int k,int l,int r,int x,int y) 24 { 25 if(l==x&&y==r) return v[k]; 26 int mid=(l+r)>>1,ans=tag[k]; 27 if(x<=mid) ans=max(ans,query(k<<1,l,mid,x,min(mid,y))); 28 if(y>mid) ans=max(ans,query(k<<1|1,mid+1,r,max(x,mid+1),y)); 29 return ans; 30 } 31 }; 32 struct segy 33 { 34 segx v[3005],tag[3005]; 35 void change(int k,int l,int r,int x,int y,int val) 36 { 37 v[k].change(1,1,S,qd,qu,val); 38 if(l==x&&y==r) {tag[k].change(1,1,S,qd,qu,val);return;} 39 int mid=(l+r)>>1; 40 if(x<=mid) change(k<<1,l,mid,x,min(mid,y),val); 41 if(y>mid) change(k<<1|1,mid+1,r,max(x,mid+1),y,val); 42 } 43 int query(int k,int l,int r,int x,int y) 44 { 45 if(l==x&&y==r) return v[k].query(1,1,S,qd,qu); 46 int mid=(l+r)>>1,ans=tag[k].query(1,1,S,qd,qu); 47 if(x<=mid) ans=max(ans,query(k<<1,l,mid,x,min(mid,y))); 48 if(y>mid) ans=max(ans,query(k<<1|1,mid+1,r,max(x,mid+1),y)); 49 return ans; 50 } 51 }T; 52 int main() 53 { 54 D=read();S=read();N=read(); 55 int d,s,w,x,y; 56 for(int i=1;i<=N;i++) 57 { 58 d=read();s=read();w=read();x=read();y=read(); 59 ql=x+1;qr=x+d;qd=y+1;qu=y+s; 60 int ans=T.query(1,1,D,ql,qr); 61 T.change(1,1,D,ql,qr,ans+w); 62 } 63 qd=1,qu=S; 64 printf("%d\n",T.query(1,1,D,1,D)); 65 return 0; 66 }