日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[学习笔记]标记永久化

發(fā)布時間:2023/12/31 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [学习笔记]标记永久化 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

線段樹出了名的操作是lazy標記。

普通lazy標記涉及到pushup和pushdown

這個pushup只涉及兩個兒子合并,并且兩個兒子是兩個點。

但是有的時候,兩個兒子是兩個樹,pushup復雜度就爆炸了。

給你一個線段樹的樹套樹,外層的線段樹pushup一下,就對應里面每個節(jié)點對應pushup。O(n^2log^2n)優(yōu)秀數(shù)據(jù)結(jié)構(gòu)誕生辣

?

還有的時候,主席樹要區(qū)間修改。

每次修改操作我們在之前基礎上建一棵新樹,問題是,兒子是共用的,pushdown一下,之前的版本也會受到影響。涼涼。

?

所以要標記永久化。

?

標記永久化,就是標記不用pushdown,自然也不用pushup(開始建樹的時候,可能要pushup)

?

以一維線段樹區(qū)間加,區(qū)間求和為例。

add懶標記,sum是和。

upda時候,路上的sum都加上c*len;如果到了該返回的完全包含節(jié)點時候,再把add加上c。

query的時候,把路上的add都做和,到了該返回的節(jié)點的時候,返回sum[x]+addsum*len(注意這一層的add別加了就)

可以發(fā)現(xiàn),一路統(tǒng)計,一路標記下來,add,sum有機配合,就可以算出了。

可以理解為,query的時候,在x節(jié)點的父親做過的賦值用add求了出來,x子孫做過的賦值sum已經(jīng)處理完畢。所以沒有問題。

?

真正的例子:

[POI2006]TET-Tetris 3D

二維線段樹,矩形求max,矩形取max

(ps:這個題不是矩形取max的話,如果是矩形賦值,標記永久化還真做不了。。)

外層行,內(nèi)層列。

對于外層的線段樹,這個是不能懶標記的。

類比上面開兩個變量,這里我們開兩個樹。

一個mx樹,節(jié)點上的內(nèi)層線段樹記錄這若干行壓縮起來的最大值

一個tag樹,節(jié)點上。。。。。。。。。。。。所打標記的最大值

然后update,query類比即可 。

?

內(nèi)層線段樹由于兒子就是兩個點,所以隨意了。

?

代碼:(空間玄學,反正卡著邊界能過)

#include<bits/stdc++.h> #define il inline #define reg register int #define numb (ch^'0') #define mid ((l+r)>>1) using namespace std; typedef long long ll; il void rd(int &x){char ch;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x); } namespace Miracle{ const int N=1050; int n,m,k; struct node{int ans[2*N],laz[2*N];void upda(int x,int l,int r,int L,int R,int c){ans[x]=max(ans[x],c);if(L<=l&&r<=R) {laz[x]=max(laz[x],c);return;}if(L<=mid) upda(x<<1,l,mid,L,R,c);if(mid<R) upda(x<<1|1,mid+1,r,L,R,c);}int query(int x,int l,int r,int L,int R){if(L<=l&&r<=R){return ans[x];}int ret=laz[x];if(L<=mid) ret=max(ret,query(x<<1,l,mid,L,R));if(mid<R) ret=max(ret,query(x<<1|1,mid+1,r,L,R));return ret;} }mx[2*N],tag[2*N]; void upda(int x,int l,int r,int l1,int r1,int l2,int r2,int c){mx[x].upda(1,1,m,l2,r2,c);if(l1<=l&&r<=r1){tag[x].upda(1,1,m,l2,r2,c);return;}if(l1<=mid) upda(x<<1,l,mid,l1,r1,l2,r2,c);if(mid<r1) upda(x<<1|1,mid+1,r,l1,r1,l2,r2,c); } int query(int x,int l,int r,int l1,int r1,int l2,int r2){if(l1<=l&&r<=r1) return mx[x].query(1,1,m,l2,r2);int ret=tag[x].query(1,1,m,l2,r2);if(l1<=mid) ret=max(ret,query(x<<1,l,mid,l1,r1,l2,r2));if(mid<r1) ret=max(ret,query(x<<1|1,mid+1,r,l1,r1,l2,r2));return ret; } int main(){rd(n);rd(m);rd(k);int x,y,s,d,h;while(k--){rd(d);rd(s);rd(h);rd(x);rd(y);++x,++y;int ch=query(1,1,n,x,x+d-1,y,y+s-1)+h;upda(1,1,n,x,x+d-1,y,y+s-1,ch);}printf("%d",query(1,1,n,1,n,1,m));return 0; }} signed main(){Miracle::main();return 0; }/*Author: *Miracle*Date: 2018/12/9 18:33:23 */

?ps:感覺如果值不具有覆蓋性(取max)或者等價撤銷性(加減),就不能標記永久化了(賦值)

轉(zhuǎn)載于:https://www.cnblogs.com/Miracevin/p/10092806.html

總結(jié)

以上是生活随笔為你收集整理的[学习笔记]标记永久化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。