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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

链剖LCT总结

發(fā)布時間:2025/4/14 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 链剖LCT总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在搞LCT之前,我們不妨再看看喜聞樂見的樹鏈剖分。

樹鏈剖分有一道喜聞樂見的例題:NOI2015 軟件包管理器

如果你看懂題目了,你就會明白它是叫你維護一個樹,這棵樹是不會動的,要茲磁子樹求和,子樹修改,樹上路徑求和,樹上路徑修改。

樹鏈剖分就是把一個樹剖分成像這樣的東西:

一棵樹用一坨重鏈組成,重鏈之間用輕鏈連接。

對于樹上的每一個點,它和子樹大小最大的那個的根節(jié)點在同一重鏈,其他兒子另成一條新重鏈。

這樣可以證明每個點到根至多只有l(wèi)og級這么多段的連續(xù)的重鏈。

然后我們把連續(xù)的一坨重鏈用線段樹維護一下。

代碼(常數(shù)非常大

#include <iostream> #include <stdio.h> #include <stdlib.h> using namespace std; #define SIZ 266666 namespace segt { #define LC(x) ((x)<<1) #define RC(x) (LC(x)+1) int M=131072,ls[SIZ],rs[SIZ],tag[SIZ],sum[SIZ]; inline bool avb(int x) {return 1<=x&&x<=2*M; } void pd(int x) {if(!avb(x)||tag[x]==-1) return;if(avb(LC(x))) tag[LC(x)]=tag[x];if(avb(RC(x))) tag[RC(x)]=tag[x];sum[x]=(rs[x]-ls[x]+1)*tag[x]; tag[x]=-1; } void upd(int x) {pd(LC(x)); pd(RC(x));sum[x]=0;if(avb(LC(x))) sum[x]+=sum[LC(x)];if(avb(RC(x))) sum[x]+=sum[RC(x)]; } int query(int cur,int l,int r) {if(!avb(cur)||l>r) return 0;pd(cur);if(ls[cur]==l&&rs[cur]==r) return sum[cur];int mid=(ls[cur]+rs[cur])>>1;int ans=query(LC(cur),l,min(mid,r))+query(RC(cur),max(mid+1,l),r);upd(cur);return ans; } void edit(int cur,int l,int r,int x) {if(!avb(cur)||l>r) return;pd(cur);if(ls[cur]==l&&rs[cur]==r) {tag[cur]=x; return;}int mid=(ls[cur]+rs[cur])>>1;edit(LC(cur),l,min(mid,r),x);edit(RC(cur),max(mid+1,l),r,x);upd(cur); } void init() {for(int i=1;i<=M;i++) sum[i+M]=0, ls[i+M]=rs[i+M]=i, tag[i+M]=-1;for(int i=M-1;i>=1;i--){tag[i]=-1; sum[i]=sum[LC(i)]+sum[RC(i)];ls[i]=ls[LC(i)]; rs[i]=rs[RC(i)];} } } namespace lct //然而只是鏈剖 { int n,S=0,ns[SIZ],fs[SIZ],ss[SIZ], fa[SIZ],siz[SIZ],ws[SIZ],dep[SIZ], fe[SIZ],top[SIZ],X=0,ls[SIZ]; void setc(int s,int f) //setchild {fa[s]=f; ++S; ns[S]=fs[f]; fs[f]=S; ss[S]=s; } void dfs1(int cur) {siz[cur]=1; ws[cur]=0;int csc=-233;for(int x=fs[cur];x;x=ns[x]){int c=ss[x];fa[c]=cur;dep[c]=dep[cur]+1;dfs1(c);if(siz[c]>csc) csc=siz[c], ws[cur]=c;siz[cur]+=siz[c];} } void dfs2(int cur,int tp) {fe[cur]=++X; top[cur]=tp;if(ws[cur]) dfs2(ws[cur],tp);for(int x=fs[cur];x;x=ns[x]){int c=ss[x];if(c!=ws[cur]) dfs2(c,c);}ls[cur]=X; } void s2(int cur) {printf("%d\n",segt::query(1,fe[cur],ls[cur]));segt::edit(1,fe[cur],ls[cur],0); } void s1(int x) {int u=1,v=x,ds=dep[v]-dep[u]+1,sum=0;int f1=top[u],f2=top[v];while(f1!=f2){if(dep[f1]<dep[f2]) swap(f1,f2), swap(u,v);//u is deeper...sum+=segt::query(1,fe[f1],fe[u]);segt::edit(1,fe[f1],fe[u],1);u=fa[f1]; f1=top[u];}if(dep[u]>dep[v]) swap(u,v);sum+=segt::query(1,fe[u],fe[v]);segt::edit(1,fe[u],fe[v],1);printf("%d\n",ds-sum); } } int main() {int n,tmp;scanf("%d",&n);for(int i=2;i<=n;i++){scanf("%d",&tmp);lct::setc(i,tmp+1);}lct::dfs1(1); lct::dfs2(1,1);segt::init();int Q;scanf("%d",&Q);char iu[20]; int x;while(Q--){scanf("%s%d",iu,&x);++x;if(iu[0]=='i') lct::s1(x);else lct::s2(x);} }

稍微做一點說明吧。

dfs1這個函數(shù)就是基本的一些處理,dfs2這個函數(shù)是用來分配輕重鏈的。

然后子樹操作就只要把這個子樹里面的所有重鏈在線段樹里面修改就行。

鏈的代碼:

void s1(int x) {int u=1,v=x,ds=dep[v]-dep[u]+1,sum=0;int f1=top[u],f2=top[v];while(f1!=f2){if(dep[f1]<dep[f2]) swap(f1,f2), swap(u,v);//u is deeper...sum+=segt::query(1,fe[f1],fe[u]);segt::edit(1,fe[f1],fe[u],1);u=fa[f1]; f1=top[u];}if(dep[u]>dep[v]) swap(u,v);sum+=segt::query(1,fe[u],fe[v]);segt::edit(1,fe[u],fe[v],1);printf("%d\n",ds-sum); }

在u和v不在同一條重鏈上時,把u和v所在重鏈頭(就是同一條重鏈上深度最小的)中深度大的那個往上走,順路更新線段樹。

當u和v在同一條重鏈上時直接修改線段樹就可以了。此時深度比較小的那個就是lca。(你想這樣求lca的話我也沒意見

那如果是不是邊權而是點權的話就把父向邊的邊權設為點權就行,路經(jīng)詢問時記得要統(tǒng)計一下lca的點權,同樣子樹詢問的時候要統(tǒng)計一下根節(jié)點的點權。

因為每個點到根的路徑上至多有l(wèi)og級的重鏈,像這樣搞的復雜度大概是O(logn*數(shù)據(jù)結(jié)構(gòu))。如果你用線段樹來維護那就是O(log^2n)。但是實際復雜度往往到不了這個級別…

LCT和鏈剖也是類似的,也是把一個樹(或森林,下文為了方便就直接說是樹了)剖成若干條鏈,但是這里的重鏈和輕鏈有區(qū)別,每訪問一個點,我們就把它到根的路徑全變成重鏈。這個訪問操作一般叫做“access”。

在LCT中我們把這個“重鏈”叫做Preferred Edge,把一段不能再延伸的重鏈叫做Preffered Path,如果結(jié)點v的子樹中,最后被訪問的結(jié)點在子樹w中,這里w是v的兒子,那么就稱w是v的Preferred Child,如果最后被訪問過的結(jié)點就是v本身,那么它沒有Preferred Child。

access操作看起來像這樣:

LCT主體用splay維護,和鏈剖一樣,splay里面的一條重鏈是存在一棵子樹里的。但是這顆splay的father比較特殊…如果一個點它是這條重鏈splay里面最上面的一個點,那么它的父親就是樹上實際的父親,否則就是正常splay的父親。

剩下的事情呢如果泥會splay就比較trivial了。你要access一個點,你就把它旋到這條重鏈的頂上,此時它的父親就是樹上的父親了對吧。然后把右子樹接到這條重鏈上面的下一個點。然后把“下一個點”設為這個點,再往父親走。

那么為什么要接右子樹呢?因為我們希望中序遍歷的時候是連續(xù)的一條重鏈…這個隨意理解一下,至于右子樹怎么辦……愛怎么辦怎么辦,因為右子樹的父親不會變啊,而且右子樹對應的也就是鏈上深度低一點的某一個點,所以并沒有什么事情。

接下來還有一個基本操作叫makeroot(x),這個操作意思是讓x成為整棵樹的根。我們先access(x)(使x到根節(jié)點為一條重鏈),然后splay(x)(使x成為這條重鏈最上面的一個點),然后再把x這棵子樹打一個翻轉(zhuǎn)標記就行了。

為什么這樣是可行的呢?因為x這個重鏈以外的東西跟根是什么并沒有什么關系,只要把x這條重鏈翻轉(zhuǎn)過來x就會在最頂上了。

然后findroot(x),找到x所在子樹在原樹上的根節(jié)點(因為makeroot可能會改變根節(jié)點)。這個最簡單,先access(x),然后splay(x),然后一直往左孩子找,找到最左邊splay一下然后返回就行。(為什么要splay回去?似乎不splay也行…復雜度玄學

然后cut(a,b),把樹中a和b的連邊切斷,搞成兩棵新樹。先makeroot(a),然后access(b),然后splay(b),最后把b的左孩子和a的父親都設為0。

還有l(wèi)ink(a,b),把a和b中間連一條邊。先makeroot(a),然后fa[a]不是為空嗎,就fa[a]=b,最后在splay(a) (又是玄學

這樣LCT就嘴巴寫完啦。代碼稍后放下一篇文章放

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

總結(jié)

以上是生活随笔為你收集整理的链剖LCT总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 日韩精品在线免费观看 | 国产精品v欧美精品v日韩 | 日本人和亚洲人zjzjhd | 依人在线视频 | 精品人妻无码一区二区三区蜜桃一 | 5月婷婷6月丁香 | 精品国产一二 | 欧美黑大粗 | 中文字字幕在线中文乱码 | 国产又粗又猛又黄又爽视频 | 制服丝袜国产精品 | 欧美精品电影一区二区 | 我我色综合 | 欧美a在线视频 | 精品人妻一区二区三区视频 | 国产视频一区二区三区在线观看 | 日本高清网色 | 蜜臀av一区二区三区激情综合 | 性插免费视频 | 亚洲精品视频一二三区 | 天天天天天天天干 | a天堂中文在线观看 | 欧美在线视频观看 | 制服丝袜手机在线 | 91亚洲欧美激情 | 国产精品久久一 | 涩涩片影院 | 在线观看视频二区 | 精品人妻一区二区三区视频 | 欧美三日本三级少妇三99 | 波多野结衣潜藏淫欲 | 新91在线| 日本免费一区二区三区最新 | 国产精品免费一区 | 国产999精品视频 | 香蕉手机网| 伊人伊网| 国产精品21p| 久久亚洲综合国产精品99麻豆精品福利 | 国产精品国产三级国产普通话蜜臀 | 三上悠亚影音先锋 | 成人性生活免费看 | 91网址在线观看 | 韩国av在线 | 日本乱大交xxxx公交车 | 国产亚洲精品一区二区三区 | 欧美激情久久久久 | 亚洲中文字幕一区二区在线观看 | 操欧美老逼 | 久久伊人操 | 色吧在线观看 | 美女黄色片网站 | 日本a级大片 | 成人免费小视频 | 青青青青在线 | 中日韩黄色片 | 天堂俺去俺来也www 欧美大片在线播放 | 免费在线观看成人av | 婷婷激情图片 | 色呦呦免费视频 | 免播放器在线视频 | 男人午夜av| 欧美超碰在线 | 亚洲天堂中文字幕在线 | 精品人伦一区二区三区蜜桃免费 | 中文字幕高清视频 | 久久青青草原 | 午夜特级毛片 | 国产精选在线观看 | 日韩人妻无码一区二区三区 | 午夜久久一区 | 欧美黄色录像片 | www.国产色| 久久一卡二卡 | 超碰2021 | 国产网站视频 | 中文字幕一区二区三区手机版 | 私人午夜影院 | 亚洲久久色| 特级丰满少妇一级aaaa爱毛片 | 国产男男一区二区三区 | 在线看视频 | 欧美视频你懂的 | 国产成人影视 | 特级西西444www高清大视频 | 久久精品视频无码 | 成人h动漫精品一区二区下载 | 成人激情视频在线 | 欧美少妇一区 | 黄网视频在线观看 | www午夜 | 欧美日韩国产不卡 | 97夜色| 久久婷香 | 欧美另类视频在线观看 | 国产成人av网 | www.日韩视频 | 蜜桃视频在线观看一区 | 5月婷婷6月丁香 |