線性基 (異或和求最大值)例題 無效位置

2021-08-19 16:41:04 字數 3210 閱讀 4331

對於給出多個數,求異或的最大值時,通常需要用線性基來處理

什麼是線性基呢?

對於原陣列,我們試圖用最少個數作為基礎,用這些數之間的異或就可以表示所以子集合的異或和,而這些數即基礎,稱之為線性基,類似於用10個數來表示1~1023的所有數的道理

所有基線性相關

我們用陣列a來表示線性基,a[i]表示基當中最高位為第i位的基

基的插入過程為

假如當前數v最高位i所在的基a[i]已經存在(a[i]!=0),那麼這個數通過基a[i]轉化成低位的數:v^=a[i]

假設不存在,就拿當前數作為基a[i]

eg:

假設給出下列二進位制數

1100 ,1011 ,1110 ,1101 ,0001 ,0101

1100,因為a[4]==0 所以a[4]=11001011,a[4]存在,所以1011->0111,故a[3]=01111110,a[4]存在,->0010,a[2]=00101101,a[4]存在,->0001,a[1]=00010001,a[1]存在,->0000

0101,a[3]存在,->0010,a[2]存在,->0000

很容易發現,只要滿基了,就可以表示所有的數了,因為相當於二進位制每一位都可以控制0或1

本質:低位基都是由數經過高位基轉化而來

void insert(int val)

val^=a[i];}}

if(val==0)a[0]=1;//可以通過異或變成0,用於找最小值

}

和插入的過程類似,從高到低,只要同位的最高位基存在,就異或,到最後成功由這些基轉化成0就說明存在

int fin(int

val)

}return 0;

}

因為基的性質,只要把另乙個線性基裡面的基當成數插入就可以了(相當於把其他的基通過當前線性基內的基轉化一下)

void merge(int b)

}

所有原數之間的異或和等價於基之間的異或和,所以找最大值,只需要判斷所有基的取與不取即可

找最大值時,從高位基開始找,取某個基時使答案變大,那麼就是需要取的

int finmax()

return ans;

}

找最小值時,因為基代表了最高位是哪一位,所以最小的那個基就是答案(當然,要考慮乙個基都沒有的情況)

int finmin()

}

#include

using

namespace

std;

struct linear_bace;

typedef linear_bace lb;

#define n 100009

struct linear_bace

val^=a[i];}}

if(val==0)a[0]=1;//可以通過異或變成0

}int fin(int val)

}return

0; }

int finmax()

return ans;

}int finmin()

return

0; }

}e[n];

void merge(lb &a,lb &b)

b=a;

}

原題:wannafly挑戰賽14 e-無效位置

題意

給出n個數,會依次刪除所有數,求每次刪除前剩下陣列ans

定義ans=從任意乙個完整區間(連續的沒有數被刪除)內找任意個數,使異或和最大

解析

異或和最大值,明顯的線性基,但是線性基只要insert,而沒有erase,所有我們離線處理刪除操作,正向刪除相當於反向插入,這樣基本思路就有了

接下來要處理完整區間的問題

把每個位置都放乙個線性基,每插入乙個點,如果左右連著一段已經處理出來的有效區間,那麼就可以合併到一起

怎麼合併,和哪個合併?

每插入乙個點,那個點接壤的點如果是已有區間的一部分,那麼就一定是端點。

所以就可以用兩個端點的相關值來表示這個區間的相關值

相關值有:左端點和右端點位置,乙個區間的線性基

那麼就用l[i]表示i所在區間的左端點位置,r[i]同理

insert 位置p時,如果連著p-1,就可以通過l[p-1]知道這個區間的左端點位置

**

#include

using

namespace

std;

struct linear_bace;

typedef linear_bace lb;

#define n 100009

struct linear_bace

val^=a[i];}}

if(val==0)a[0]=1;//可以通過異或變成0

}int fin(int val)

}return

0; }

int finmax()

return ans;

}int finmin()

return

0; }

}e[n];

void merge(lb &a,lb &b)

b=a;

}int nu[n];

int ord[n];

int f[n],l[n],r[n];

int main()

else

if(f[p-1]&&f[p+1])

else

if(f[p-1])

else

a.push(ans);

}while(!a.empty())

}

1578 異或最大值(思路)

有兩個正整數n,k k n 10000 1到n中至多任取k個數,求這些數異或能得到的最大值 第一行乙個整數t,表示t組輸入,t 1000 接下來t行,每行兩個整數用空格分隔,表示n,k。每組資料輸出乙個整數佔一行,表示異或能得到的最大值複製 1 4 14思路 對於k 1時不能異或只能取最大的自己,對...

P3812 模板 線性基 求最大值)

這是一道模板題。給定n個整數 數字可能重複 求在這些數中選取任意個,使得他們的異或和最大。輸入格式 第一行乙個數n,表示元素個數 接下來一行n個數 輸出格式 僅一行,表示答案。輸入樣例 1 複製 2 1 1 輸出樣例 1 複製 1 1 n 50,0 si 250 1 leq n leq 50,0 l...

CSU 1216(異或最大值)

csu 1216 題目簡述 經典題目,求乙個陣列中兩個數異或運算的最大值。題目極其簡單,但是要求的複雜度需要達到o n log n 還是比較難的。解題思路 總的思路就是構建一棵0 1字典樹,然後乙個數讓查詢乙個與其異或結果最大的數的效率達到o log n 這裡因為異或的特殊性質,可以使用貪心法則來實...