巧妙運用位運算

2022-05-22 16:21:11 字數 2875 閱讀 7634

本文旨在通過兩道巧妙運用位運算的題,認識位運算的魅力

題意:

給定兩個序列\(a,b\),求\(a,b\)的最長公共子串行

\(|a|,|b|\le 10^5\)

時限:\(5s\)

目前求任意兩序列的最長公共子串行,是沒有複雜度低於\(o(|a|\cdot |b|)\)的演算法的

回顧經典的\(o(|a|\cdot |b|)\)

\[f_=max(f_,f_,f_+[a_i+b_j])

\]顯然有如下性質:

\[\begin

&f_\le f_\\

&f_\le f_\\

&f_-f_\le 1\\

&f_-f_\le 1

\end\]

令\(m_=f_-f_\)

考慮轉移

我們將\(\text_\)劃分為若干段,每段以乙個\(1\)結尾:

[000...01][000...01][000...0]

^^ ^

12 |b|

考慮\(a_i\)出現在\(b\)中的位置集合,令其為\(\text\)

令\(\text_|\text\)

對於\(\text_\)的每一段,保留\(\text\)最前面的乙個\(1\),則為\(\text_i\)

例如

$m_$=[000...01][000...01][000...0]

$ab$=[110...00][000...00][001...0]

$m_i$=[100...00][000...01][001...0]

我們已知了轉移方式,考慮如何通過位運算得到

對於某一段如:x=[0011001]

考慮前導0變成1,第乙個1變成0:[1101001]

異或上x,得到[1110000]

在按位與上x,得到[0010000]

我們將\(\text\)翻轉,第一步操作變成

x=[1001100]

[1001011]

這個意義是\(-1\),這是一段的操作,對所有段如何快速進行呢

發現我們將\(\text_\)整體翻轉後

再左移,給最右邊填上\(1\),效果為:

$m_$=[000...0][100...0][100...0]

^ ^^

|b| 21

[000...1][000...1][000...1]

這恰好使得每一段都變成1

那麼直接減即可,具體細節見**

將矩陣的行壓成\(k\)塊,即可實現\(o(|a|\cdot k)\)的時間複雜度

以下**在\(n,m=10^5\),不開任何優化的情況下,跑進1s

#includetypedef int ll;

typedef unsigned long long ull;

const ll maxn=1e5+9;

ll read()

while(c>='0' && c<='9')return x*f;

}ll n,m,ans;

ll a[maxn],b[maxn];

ull dp[maxn/63],pos[maxn][maxn/63];

int main()\)為\(\\)的某個排列)

每個點還有乙個顏色\(c_i\)

\(q\)次詢問,每次給定\(l,r,d,u\),求集合\(\\)的顏色個數

\(n,q\le 10^5\)

令\(a_\)為第\(i\)次詢問是否包含顏色\(c\),考慮得到其

顯然可以將\(i\in[l,r],p_i\in[d,u]\)可以拆開

令\(x_\)為第\(j\)次詢問是否滿足\(l_j\le i\le r_j\),我們對於\((l_j,j)(r_j+1,j)\)進行掃瞄線,能很輕鬆的得到

令\(y_\)為第\(j\)次詢問是否滿足\(d_j\le i\le u_j\),同理可得

那麼\((x_i\and y_j)_j\)即為點\(i\)是否被包含在第\(j\)次詢問中

現在可以很簡單得到\(a\)

矩陣\(a\)顯然為01矩陣,需要將各行按列相加,得到答案

對於每列,這裡我們如此維護其答案:

令\(cnt_i\)為第\(i\)列目前的答案

\(cnt_i=\sum\limits_^ 2^k\cdot c_\)(其中\(c\)為01矩陣)

假設這裡\(cnt_i\le n\),那麼改寫成

\(cnt_i=\sum\limits_^ 2^k\cdot c_\)

令\(logn\)為矩陣的行數,稱為\(h\)

那麼我們分治,對於顏色\(\in[l,mid]\),令其矩陣為\(c_0\),對於顏色\(\in(mid,r]\),令其矩陣為\(c_1\)

考慮合併\(c_0,c_1\):\(c'=c_0+c_1\),假設\(c_0,c_1\)的\(h_0,h_1\)均為\(l\),為了方便,則矩陣\(c\)的\(h=l+1\)

合併的過程,相當於是二進位制高精,考慮進製,很容易實現

分析其時間複雜度

令顏色種類為\(n\),令\(k\)為將矩陣\(c\)的行壓成的塊數

\(t(n)=2t(n/2)+klogn\),\(k\)為常數,提取出來

\(t(n)=2t(n/2)+logn\),運用主定理得到\(t(n)=n\)

時間複雜度為\(o(k\cdot n)\)

巧妙運用 按位或「 」 運算

今天在學習collections的原始碼時,看到下面的 聯絡之前自己寫的程式,感受到下面這段 確實巧妙 1 public static boolean addall collectionc,t.elements 下面簡單介紹 t.elements 可變引數列表,元素為泛型t或t的子類。這是類似於 這...

位運算的巧妙應用

與運算 或運算 異或運算 非運算 移位運算 和 題目要求 用乙個表示式,判斷乙個數x是否是2的n次方,即2,4,8,16 等,要求不可以用迴圈語句。解析 2,4,8,16這樣的數轉化成二進位制是10,100,1000,10000。如果x減去1後 低一位並且二進位制的每一位都是1 這個數與x做與運算,...

位運算的巧妙設計

位運算子 例子名稱 結果 a b and 按位與 將把 a 和 b 中都為 1 的位設為 1。a b or 按位或 將把 a 和 b 中任何乙個為 1 的位設為 1。a b xor 按位異或 將把 a 和 b 中乙個為 1 另乙個為 0 的位設為 1。a not 按位取反 將 a 中為 0 的位設為...