求集合中選一個數與當前值進行位運算的max


求集合中選一個數與當前值進行位運算的max

這是一個聽來的神仙東西。
先確定一下值域把,大概\(2^{16}\),再大點也可以,但是這里就只是寫寫,所以無所謂啦。

我們先看看如果暴力求怎么做,位運算需要給定\(01/10,00,11\)的關系,總共\(8\)種。
如果是暴力的話,我們的方法有兩種,
第一種是比較喜聞樂見的,
我們對於當前數\(x\),暴力計算所有存在的數\(a_i\)中,\(x\oplus a_i\)的最大值,這樣的復雜度是\(O(2^{16})\)的。
另外一種也是不難考慮到的,
我們對於每個可能出現的數維護一個當前所有數的最大值。
也就是對於所有值域中的數,維護一個答案\(ans\)
然后依次插入所有集合中所有的數\(a_i\),每次暴力計算所有的答案的最大值,
也就是\(ans[x]=max\{x\oplus a_i \}\),這樣子詢問的時候可以\(O(1)\)查詢。

兩種方法一種是插入\(O(1)\)詢問\(O(n)\),另外一個是插入\(O(n)\),詢問\(O(1)\)
我們把兩種東西結合一下,這樣可以得到一個\(O(\sqrt n)\)的方法。
大致的方法如下:
我們對於每個數從中間分開,拆成前\(8\)個二進制位和后\(8\)個二進制位。
這樣子我們可以預處理一個數組\(pre[i][j]\)
表示集合中一個前\(8\)位是\(i\)的數,后\(8\)位能夠和\(j\)進行位運算的最大值。
這樣子\(i,j\)都是一個\(8\)位的數,總的空間和上述方法一樣。
因為位運算是可以按位貪心的,所以對於查詢一個數\(x\)
我們把它拆成\(x=a\times 2^8+b\)
每次先暴力\(for\)所有可能的前\(8\)位,找到與\(a\)能夠構成最大值的那些數,
然后對於找到的所有數的前八位\(p\),直接查\(pre[p][b]\)
因為前八位更大的數一定更大,那么影響結果的就只剩下后八位了,
把兩個部分拼接起來就好了。
這樣子暴力\(for\)前八位的復雜度是\(O(2^8)\)
查找后面部分最大值的復雜度是\(O(1)\)
所以這樣子總的復雜度\(O(2^8)\)
而對於集合中插入一個數,前\(8\)位唯一確定,每次只需要預處理后\(8\)位的結果。
時間復雜度還是\(O(2^8)\)
總的復雜度還是\(O(2^8)\)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM