Codeforces Educational Round 23
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