1. 程式人生 > >Codeforces Educational Round 23

Codeforces Educational Round 23

value trie樹 進制 過程 round lazy 是我 線段樹 val

A

emmmmmmmmm

B

emmmmmmmmm

C(套路)

題意:

給定n和s(n,s<=1e18),計算n以內有多少個數x滿足(x-x的各個位置數字之和)>=s

分析:

容易想到如果x相對於s很大很大,那麽肯定是滿足條件的

那些小於s的數,肯定是不行的

於是x就可以從s開始,往後枚舉1e6個,去判定這1e6個有多少個是滿足條件的,再往後的那些x肯定是滿足的,直接算出多少個就行了

D(插板法)

題意:

給定一個長度為n(n<=1e6)的數列,對於這個數列的一個連續的子列,定義value=該子列的最大值-最小值。求這個數列所有連續子列的value和

分析:

肯定要分開考慮,考慮一個數字a[i]作為最大值能貢獻多少組子列,作為最小值能貢獻多少組子列(作為最小值的時候是負貢獻)

下面以求最大值為例,求最小值同理

問題就轉變成了要求出每個數字a[i]往左往右至多擴展多長距離才遇見第一個比其大的數

可以先把所有數字排序,然後按照從大到小的順序將數字插入到對應位置上,那麽對於當前考察的a[i],離其最近的左邊隔板和右邊隔板就是它作為最大值的區間

這一過程可以用set來維護

時間復雜度O(nlogn)

E(Trie樹處理異或比較問題)

題意:

在一個初始為空的集合中有1e5個操作:

  1)插入一個數字p

  2)刪除一個數字p(保證合法)

  3)輸入p和l,詢問當前集合中有多少個數字x滿足p xor x < l

分析:

經典的Trie樹處理異或比較問題

這裏有個刪除操作

實際上在Trie樹上就直接暴力刪就行了,復雜度O(logA)的

具體的就是從root開始沿著p數字的二進制位走,如果發現當前某一分支的sum==1,就說明這個分支下面只管理著一個節點(這就是我們要刪的),所以直接在這裏把樹枝斷掉就行了

復雜度O(qlogA)

F(線段樹)

題意:

在一個初始為空的集合中有1e5個操作:

  1)將[l,r]這些數加入到集合中(如果數字重復就只保留一個)

  2)將[l,r]這些數從集合中刪除(如果集合中本來就沒有某個數,那這個數就不操作)

  3)將[l,r]這些數在集合中的出現情況反轉,也就是將原本在集合中存在的數刪除,原本不在的數加入

l,r<=1e18

在每次操作之後,輸出集合的mex,即最小的沒有出現在集合中的正整數

分析:

每次的結果肯定會在所有的l、所有的r+1,以及數字1中產生

考慮先把所有數據讀入,將這些數字離散,建立一個線段樹

對於操作1和2,就是將線段樹一段區間賦值,sum直接維護

對於操作3,就是將線段樹一段區間異或(只有0和1),sum=len-sum

發現這個線段樹是可以lazy的,並且可以合並

對於查詢,就是尋找線段樹上最左邊的0的點,直接根據一個節點k的sum[lchild]與len[lchild]的大小關系即可判斷是向左走還是向右走,查詢也是O(logn)的

時間復雜度O(nlogn)

Codeforces Educational Round 23