近期總結2

莫隊:https://www.cnblogs.com/WAMonster/p/10118934.html

使用條件:查詢連續一段區間,且擴張或縮小區間兩端的複雜度優秀.

做法:離線,把序列分塊,把L,R按所在塊的編號從小到大雙關鍵字排序.每次移動查詢.

優化:排序時l遞增,在l的塊爲奇數時R遞增,爲偶數時R遞減.

帶修莫隊:加入一個修改的時間戳,也作爲關鍵字排序,然後分的塊大小爲n^(3/4)*t^(1/3)或者記不住的話就是n^(2/3).

樹上莫隊:給樹弄一個歐拉序,就是每個點進來時記錄在隊,出去時也記錄在隊,共記錄兩次.然後查詢x到y的路徑.設每個點的編號x首次出現的位置first[x],最後出現的位置爲last[x],令first[x]<=first[y](不滿足則swap),如果lca(x,y)=x,則直接把[first[x],first[y]]的區間扯過來用,反之使用[last[x],first[y]]區間再在查詢時加上公共祖先.

回滾莫隊:有的擴張容易縮小困難(比如維護的時最大值).那我們就只讓它擴張.具體來說就是先暴力處理在同一塊的查詢,然後按l所在的塊逐塊搞定. 每次將R向後推進,l則復原在塊尾,然後向前推進.

分塊:

區間衆數:https://www.docin.com/p-679227660.html

結論:一段區間的衆數,它的可能選項爲它的一個子區間的區間衆數,和除去這個子區間外的所有數(這些數可以包含子區間內的數.

若查詢l,r在一塊中則暴力,在不同塊中,則衆數由l的散塊,r的散塊,和中間的整塊構成.

預處理任意兩塊間的衆數,再預處理f[i][x]表示第1~i塊中x出現的次數,g[k][i][x]表示在第k塊中,到第i個,x出現次數(預處理時空複雜度O(n*根號n)).

根據結論,可得衆數只可能由整塊的衆數,散塊的所有數共2*根號n個構成,一個一個去計量它們在區間中出現的次數,去比較,其實預處理之後就是O(n*根號n)了.

如果還有修改操作,我們就要把塊的個數變成L=n^(1/3),這樣每次修改一個數,最多可能會影響L*L個塊組之間的答案.

對每塊之間,維護每個值的出現次數以及最大的出現次數.再將更改的那個值所在塊的g修改一部分.

O((n+q)^(2/3))

分塊題目http://hzwer.com/8053.html

大概思路:預處理,處理整塊,處理散塊. 有時數組可以用數據結構替代.有些操作如開方,整體賦值,很容易就會把大量數弄得相等,若一個塊內數字相等可以判掉. 如果有插入的,一個塊內內容太大,就拆成兩半或重新分塊.

異或高斯消元:

M[0][0]*x[0]^M[0][1]*x[1]^…^M[0][N-1]*x[N-1]=B[0]
M[1][0]*x[0]^M[1][1]*x[1]^…^M[1][N-1]*x[N-1]=B[1]

M[N-1][0]*x[0]^M[N-1][1]*x[1]^…^M[N-1][N-1]*x[N-1]=B[N-1]
其中每個係數都是0或1.

然後其實和普通高斯消元差不多,先找到一個第一列係數爲1的行,扔到第一行,並靠它消去其它所有第一列係數也爲1的行的那個1.其它類推.

線性基:https://blog.csdn.net/a_forever_dream/article/details/83654397

定義:對於一個序列,在它的線性基中選出一個或若干個數,異或起來,一定可以表示出這個序列中的所有數字.

性質:線性基中沒有多餘的數字,每一個數字都是有用的,也就是說對於線性基中每一個數字,它都不可以由其它數字表示.一個序列可能存在多個線性基,但每個線性基的元素個數都是相同且最少的.

構造方法:在序列中每次枚舉一個x,判斷它是否能夠插入線性基中.具體來說定義f[i]表示二進制第i位爲1且最高位爲第i位的一個線性基中的元素.從高位到低位枚舉位數,如果x在那一位上有值,且f[i]暫時沒值,就把f[i]賦值成x,跳出.如果x在那一位上有值,且f[i]也已經有值,就要把x異或上f[i]然後繼續.

這樣構造出來的線性基並不能滿足一個線性基元素上最高位的1是唯一的,因此還要消去一些位上的1.(這樣處理後也是另一種形式的線性基)

求一個序列中元素異或起來的最大值:

因爲線性基中的元素異或起來所能得到的值,和序列中元素異或起來所能得到的值,是一樣的.所以直接看線性基.從高到低枚舉,如果異或f[i]能變大就異或.

求最小值:直接找線性基中最小的那個元素吧.(因爲它佔據最小位,讓它異或別人它一定更大

求第k小:對於每一個f[i]有值的位,在第i位上它的1都是唯一的,也就是說選它或不選它兩種可能就會造成兩種不同的異或結果.所以如果k的第i位爲1時就選,反之就不選.第k大選的條件相反.

判斷一個x是否可以由線性基中的元素構成,且由哪幾個:

嘗試把x插入線性基中,失敗則是可以構成,而一路上異或的線性基元素就是構造方法,記錄下來.

LCT:

https://www.cnblogs.com/flashhu/p/8324551.html

https://blog.csdn.net/blue_cuso4/article/details/78618811

開坑!

LCT是支持樹的連邊斷邊的一種數據結構.(只講基礎了擴展我真的學不會

有一棵原樹,有一棵輔助樹,原樹上有些邊是重邊,有些是輕邊.但它的重邊和輕邊並非固定的,而是可以變化的.

每一條重鏈,用splay按深度維護.每個splay呢,由它的根,向上連一條有向邊,連的對象呢,是splay中那個深度最小的點的父親.

這些有向(兩個splay間的邊)無向(每個splay內部的邊)的邊呢,就構成了一棵輔助樹.

LCT有幾個基本操作:

access(x):意思就是將原樹中的點x到根節點的路徑上,每一條都變成重邊.注意此時將x的所有重兒子斷掉,x是所屬splay中最深的點(所以它沒有右兒子了.

具體來說呢,分爲幾個步驟:

1.將x點(操作點),splay到當前splay的根,然後把它的右兒子單方面斷掉,(如果這不是第一次操作,將接上上一次操作的點作爲x的右兒子

2.將操作點切換爲單向邊所指的父親,進入另一棵splay,然後返回操作1.

reverse(x):換根,將原樹的x節點變成整棵樹的根(勢必會帶來些深度的變化)

因爲原樹是虛樹,在原樹上變換其實是在輔助樹上變換.

先access(x),這樣整棵樹的根與x就在同一個splay中了.接着將x轉到splay的根(因爲access斷掉了x下方的重兒子,所以x在splay是沒有右兒子的,相當於x在splay中深度最大).

現在深度最大的點,要把它當作深度最小的,原來深度最小的根,則變成深度最大的,這就相當於要將整個splay翻轉過來,該棵splay中,左兒子變成右兒子,右兒子變成左二子(怎麼有種禮崩樂壞的感覺. 而不在該棵splay中的點,他們的深度關係並不發生改變(深度可能是有改變,但彼此間深度大小關係不變),於是不用翻轉.

froot(x):找到x所在原樹的樹根(主要是用來判斷聯通性的,froot(x)==froot(y)才聯通)

先access(x)打通它和根的通道,接着將x點splay到splay的根,原樹的根深度最小,一定在這棵splay的最左邊,不斷往左找(記得下傳翻轉標籤.

link(x,y):將兩個不連通的點聯通,換言之,將它們所屬的兩棵樹合併.

首先進行reverse操作,將一個點作爲它所在樹的根,然後將這個點的father單向接到另一個點上,連完了一條輕邊.

當然如果題目不保證x,y之前不連通的話,還要判斷froot(x)是否等於froot(y).

cut(x,y):將x,y之間的邊斷開.

先reverse(x)將x作爲根,然後access(y)使x與y在同一棵splay中,然後將y旋轉到splay的根,由於x,y本來有邊相連,且x深度比y淺,所以這時x必然在它的左節點,把這條邊徹底斷掉吧.

如果題目沒有保證x,y本來相連,那就要麻煩一些.

判斷x,y相連有三個條件:

1.它們兩在同一個原樹中.  

2.將x定爲原樹的根,access(y)後,splay(x),則y的父親要是x.

3.此時y沒有左兒子.

關於條件的解釋:

1.不在同一棵樹不可能相連啦,pass!

2.access(y)後,x與y在同一棵splay中,並且y下面的重兒子都被斷掉了,也就是說y是深度最大的那個.y一定不會位於某個點的左側,如果x,y不直接相連,那麼它們的中序遍歷x,y中必定有點夾着.

3.就算是x,y在輔助樹上直接相連,在原樹中它們也不一定直接相連.因爲是中序遍歷,如果y有左兒子,則中序遍歷從x下來必定先到y的左兒子,這樣x,y就不在原樹直接相連了.

板題:https://www.luogu.com.cn/problem/P3690

Over!

歐拉函數:

定義φ(x)表示在[1,x]中與x互質的數的個數,其中φ(1)=1.

公式是:

其中pi爲x的質因子,且pi都互不相同(重複的質數因子就只算一個

歐拉函數有幾個性質:

1.積性函數.也就是說若m,n互質,則

2.若x是質數,φ(x)=x-1.

3.若x是質數p的k次方(即x=p^k),則φ(x)=x-x/p=p^k-p^(k-1)=(p-1)*(p^(k-1)). (除了p的倍數,其餘的[1,x]中的數都與x互質,而[1,x]中是p的倍數的有x/p個.)

4.當x是奇質數時,φ(2x)=φ(x)*φ(2)=φ(x)=x-1

於是如果我們要求單個的φ(x),我們可以把x分解質因數,x=p1^a1*p2^a2*p3^a3.....,根據積性函數的性質,φ(x)=φ(p1^a1)*φ(p2^a2)...,然後根據性質3,φ(p1^a1)=p1^a1-p1^(a1-1).其它類推.(其實也可以不用管這種zz做法,直接按定義來就行了.分數的話用x來除一定可以除盡.

如果我們要求出1~n中所有的φ(i),就要根據積性函數的性質.

令n=m*p,p爲質數,則若m%p==0,φ(n)=φ(m)*p(這個把它按照定義化出來就可以證明),反之φ(n)=φ(m)*(p-1)(根據積性函數性質)

既然這樣,我們可以從小到大找到每個數,隨便找它的一個質因數,然後用上式.

歐拉函數在反演中有兩條式子:

就是說n的所有約數的歐拉函數和等於n (其實把G(n)當作n,φ(d)當作F(d),這個形式就是莫比烏斯反演的形式.

(那個m應該是n纔對) 左邊通分,兩邊同去n,然後用上面的莫比烏斯反演形式來反演

反演:

(最討厭這些數學內容了

這裏就是說s和x是兩個集合,其中x要保證爲s的子集,G(s)=所有合法的x的F(x)之和.

然後我們想想,G(x)=F(x)+F(x所有其它的子集) ,F(x)=G(x)-G(所有大小比x少1的子集)+G(所有大小比x少2的子集),用到容斥.

(這裏的x,s就不再是集合而是數字了

本質也是容斥.注意是要不同的質數構成纔算,相同的就爲0了

幾個高級(沙雕)公式

組合數可以證明.d作爲m的一個約數,它可能包含奇數個質因子,也可能有偶數個質因子,還可能有重複而不算.

把F(n)當作1,把G(d)當作,發現形式一毛一樣.然後反演回去可得

 

莫比烏斯反演的另一種形式:,其實就是變成了每個要是它的倍數

未完待續。

圓方樹:

基礎是一棵仙人掌。什麼是仙人掌呢,就是說連通圖中的每一條邊都最多隻在一個環中。

對於每個環中的點,我們新建一個方點,把它們彼此間的連邊刪去,並且每個點都連向那個方點。

我們稱原圖中的點叫圓點。

這樣仙人掌變成了一棵圓方樹。

圓方樹有幾個顯然的性質:

1、方點不會直接和方點相連。

2、它是一棵無根樹(即無論欽定哪個點爲根,它的形態都是一樣的。

3、令仙人掌中的根節點爲p,節點q的子仙人掌的定義爲:刪去p到q的所有簡單路徑(即不重複經過一個點的路徑),q所在的連通塊的點集。我們發現,節點q的子仙人掌就是圓方樹中節點p的子樹(自己畫圖可證)

 

線段樹優化連邊:

我們要令區間[a,b]中的每個點與區間[c,d]中的每個點連邊。如果是暴力的連邊需要枚舉每個點對,我們希望進行優化。
建立兩棵線段樹,一棵叫入樹,一棵叫出樹。都是一樣的結構。作用顧名思義。
入樹中每個點都向它兩個兒子連零邊,出樹中每個點都向它父親連零邊。
至於爲什麼是這樣子的,想想我現在能夠到一個區間,是不是自然能夠到它的子區間?
我現在要出發,我從我的父親區間出發,那個路程是不是也沒有問題呢?
相反 我能到一個區間,不一定能夠到它的父親區間,因此入樹不往上連邊。
我能從一個區間出發,能代表我能從它的父親區間出發嗎?因此出樹不往下連邊。
然後入樹中每個點都向出樹中的對應節點連零邊(進入改點之後自然能從改點出)。
至於題目給出的區間,找到線段樹上對應的節點,從出樹連向入樹。
然後跑dij。

 

點分治:

核心思想是每次找到一個重心,然後欽定路徑一定要經過重心,計算答案。
在從重心擴散尋找路徑的途上,不要走那些曾經作爲重心的點。
合併子兒子的路徑要用容斥的思想,刪掉同一個子兒子樹中的路徑兩兩合併的情況。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章