二维线段树区间更新啊
树套树的外层树,如果是线段树的话一般似乎不能打标记?(毕竟标记不好下传)
然而起码对于这题是可以的...对于外层线段树,每个节点放两个值dat和setv,分别是得到的值和修改操作留下的标记。
然后外层线段树要标记永久化...标记永久化之后,标记的定义不一样了。
这道题里用dat[i]表示i节点表示的整段区间都达到的值,setv[i]表示i节点表示的区间的最大值。
这样进行修改操作的时候,更新所有经过的节点的setv(因为只要经过该点,那么该点表示的区间和目标区间一定有相交部分),更新被目标区间完全包含的区间所在节点的dat(自然整段都达到那个值了)
进行查询操作的时候,"所有经过节点的dat"和"所有被目标区间完全包含的区间所在节点的setv"的最大值就是答案。
二维都一样,只不过外层线段树的查询是对于内层线段树的给定区间查询/修改
标记不下传
(一眼看起来似乎不是很对?有些信息被遗漏了?然而的确是对的23333)
(似乎修改和查询完全是对称的...)
错误记录:71行少了分号后的两个语句导致WA一片
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define lc (num<<1) 5 #define rc (num<<1|1) 6 #define mid ((l+r)>>1) 7 using namespace std; 8 int n,m; 9 namespace XXX 10 { 11 int L,R,x; 12 struct Y 13 { 14 int dat[2100],setv[2100]; 15 //dat表示整段区间都达到的值,setv表示区间最大值 16 void update(int l,int r,int num) 17 { 18 setv[num]=max(setv[num],x); 19 if(L<=l&&r<=R) 20 { 21 dat[num]=max(dat[num],x); 22 return; 23 } 24 if(L<=mid) update(l,mid,lc); 25 if(mid<R) update(mid+1,r,rc); 26 } 27 int query(int l,int r,int num) 28 { 29 if(L<=l&&r<=R) return setv[num]; 30 int ans=dat[num]; 31 if(L<=mid) ans=max(ans,query(l,mid,lc)); 32 if(mid<R) ans=max(ans,query(mid+1,r,rc)); 33 return ans; 34 } 35 }; 36 } 37 int L,R,x; 38 XXX::Y dat[2100],setv[2100]; 39 void update(int l,int r,int num) 40 { 41 XXX::x=x; 42 setv[num].update(1,m,1); 43 if(L<=l&&r<=R) 44 { 45 XXX::x=x; 46 dat[num].update(1,m,1); 47 return; 48 } 49 if(L<=mid) update(l,mid,lc); 50 if(mid<R) update(mid+1,r,rc); 51 } 52 int query(int l,int r,int num) 53 { 54 if(L<=l&&r<=R) return setv[num].query(1,m,1); 55 int ans=dat[num].query(1,m,1); 56 if(L<=mid) ans=max(ans,query(l,mid,lc)); 57 if(mid<R) ans=max(ans,query(mid+1,r,rc)); 58 return ans; 59 } 60 int main() 61 { 62 int Q,d,s,w,xx,yy; 63 scanf("%d%d%d",&n,&m,&Q); 64 while(Q--) 65 { 66 scanf("%d%d%d%d%d",&d,&s,&w,&xx,&yy);xx++;yy++; 67 L=xx;R=xx+d-1;XXX::L=yy;XXX::R=yy+s-1; 68 x=query(1,n,1)+w;//printf("%d\n",x); 69 update(1,n,1); 70 } 71 L=1;R=n;XXX::L=1;XXX::R=m; 72 printf("%d",query(1,n,1)); 73 return 0; 74 }