1. 程式人生 > >寒武紀camp Day4

寒武紀camp Day4

求一個 技術分享 線性 後綴 決策 一位 計數 每次 超過

補題進度:7/10

A(博弈論)

B

待填坑

C(貪心)

題意:

  一個序列是good的當且僅當相鄰兩個數字不相同。給出一個長度為n的數列,每個數字是ai。定義一種操作就是把a中某個元素拿到首位去,問最少需要多少次操作才能讓數列a變成good的。如果不可行則輸出-1。

  n<=1000,1<=ai<=n

分析:

  我們先來判-1的情況,當且僅當出現次數最多的那個數字的出現次數超過了$\frac{n}{2}$

  然後我們再來考慮一般的情況,我們把那些需要移動的數字全部拿出來記錄一下,即b[i]表示至少要把b[i]個數字i提到前面去

  假設目前一共要移動m個數字,那麽如果出現次數最多的數字的出現次數不超過$\frac{m}{2}$,那麽是很美好的,因為這樣我們一定可以用m此操作讓它們跑到前面去並且不沖突

  但是如果出現最多的次數超過了$\frac{m}{2}$,那麽我們就需要用額外的本不需要動的數字來填充其中了,討論一下即可

  註意還要討論一下第一位數字的值

D(後綴樹)

題意:

  給出一個字符串S,一個整數l,一個整數k

  |S|<=2e5,l<=2e5,0<=k<=1e12

  我們需要求出一共有多少個長度不超過l的字符串T滿足條件,答案可能很大,對1e9+7取模

  要滿足的條件是以下程序段跑出的tot的值>=k

  技術分享圖片

分析:

  考慮一個簡單的問題,給定了一個字符串T,我們要如何快速統計出tot的值

  tot的計算過程實際上是把S的每個後綴當作一個字符串,然後讓T和每個字符串去求一個LCP,然後把所有LCP相加

  很自然的想到把S的每個後綴全部加到一個Trie樹中

  那麽我們定義一個點的value是它在Trie樹的子樹中單詞節點的個數,那麽我們只需要讓T在Trie樹上走,把經過點的value都加起來就是答案了,進一步的我們可以對於每個點,求出這個點到root這條鏈上的所有value的和,那麽答案就是分叉點處的Σvalue

  這明顯可以用後綴樹優化,所以復雜度是O(n)的

  好現在我們再來考慮如何統計數目,統計數目也是很簡單的,我們只需要枚舉分叉點的位置,然後後面的那些位任意取(當然第一個自由元並不是26種),累加即可

  我們為了優化復雜度,把這個計算過程搬到後綴樹上即可,中間的計算需要在紙上算算,本質上是算等比數列求和

  建後綴樹的話,只需要建出逆序的SAM,然後按照slink建樹就行了

  時間復雜度O(n)

E(dp)

題意:

  給出n,m,p

  給出n個m維向量,向量的每一位都是0/1

  問有多少個集合S,其中異或運算在S中是封閉的,且T∈S

  答案對p取模

  1<=n<=100,1<=m<=min(2000,2^n),1<=p<=1e9

分析:

  S實際上就是包含T的線性子空間,所以就是求秩為m-rank(T)的線性子空間的個數

  我們考慮生成線性子空間的線性基的過程,從高位到低位放線性基

  每次我們有兩種決策,那就是在當前列的主元位置放一個1(上面行的對應列都必須是0),或者當前位置放置0,之前有元素的行的對應位置可以隨便填0/1

  於是我們就有了dp式子,dp[i][j]=dp[i-1][j-1]+dp[i-1][j]*2^j

  dp[i][j]表示填了i列填了j個主元的方案數

F(記憶化搜索+論文剪枝)

待填坑

G(貪心)

題意:

  給出一個1~n的排列,你可以把它分割成最多k段並且可以把這k個段進行排序,輸出你能得到的最小字典序。

  n<=1e5

分析:

  貪心著來,先把1砍出來,然後把2砍出來……

  這樣可能會面臨剩下最後一刀,但是不能把下一個數字砍出來了(因為可能需要兩刀),去討論最後一刀的情況就行了

H(標記回收線段樹)

題意:

  給出一個長度為n的數組a[],有q個操作,操作有兩種

    1 l r v :把a[l..r]全部改成數字v

    2 :撤銷目前存在的最早的1操作

  對於每次操作之後,你需要計算數組的數字和,並把它累加起來最後輸出

  n,q,v<=1e5

分析:

  有了2操作,很容易想到是可持久化線段樹,但是仔細一想,區間覆蓋操作是不支持減法的,所以可持久化線段樹好像無法做

  我們可以考慮這樣來做,第i次1操作就把對應區間的值改成i,然後刪除一個操作i就是把數組裏所有數字i刪除,變成初始狀態

  因為是按照操作順序刪除操作的,所以這樣是正確的

  我們只需要考慮用線段樹來維護這個過程就行了

  我們假設剛開始每個位置染的顏色是inf(表示沒有被染,是原來的值)

  我們現在線段樹要處理問題的核心是“將數組中所有顏色i全部刪除,變成inf,維護區間和”

  我們可以維護一下區間顏色min,如果一個區間顏色min>i,那麽就不需要進去改顏色了(因為改顏色的過程是遞增的)

  這樣每次刪除的話時間復雜度是O(顏色段數),這樣可行嗎?

  我們可以來分析一下,剛開始加入一個顏色區間,該顏色區間有log段,然後以後在染色的過程中,最多把之前的一個顏色分成兩部分,所以一次修改操作只會讓總段數多出log段,整體時間復雜度還是在O(nlogn)量級的

  有一點需要註意,在刪除一個區間的標記之後,我們還需要將它子樹裏的標記全部清空(或者在做修改操作時候清空子樹標記也是可行的),所以我們的線段樹還需要標記回收,這也是不影響復雜度的

I

待填坑

J

待填坑

K(不平等博弈)

題意:

  在一個n個點的樹上,Alice和Bob要進行博弈,首先Alice在任意一個地方下一個白棋,然後Bob在一個白棋的周圍下個黑棋,然後Alice在一個白棋的周圍下一個白棋……誰不能操作就算輸

  n<=100

分析:

  這是個不平等博弈,所以考慮用dp解決

  dp[i]表示在以i為根的子樹上下棋,Alice先手在根下,最終Alice會比Bob多走多少步

  那麽在i的k個分叉中,Bob會先選擇一個dp[u]最大的一個下黑棋,不讓Alice下白棋,然後Alice會選擇dp[u]第二大的點下白棋,然後Bob會選擇一個dp[u]第三大的點下黑棋……

  那麽把dp[u]排序後,我們去累加一下求和就能得到dp[i]的值了

  註意一點,最後dp[i]=max(dp[i],0),即如果走這個子樹Alice比Bob走的少,那麽Alice不會選擇走這個子樹

  最後看一下dp[1]的值和0的大小關系就知道是Alice贏還是Bob贏了

  時間復雜度是O(nlogn)的

寒武紀camp Day4