洛谷P5283 異或粽子 Trie 堆

2021-09-24 23:35:45 字數 1984 閱讀 6349

給出乙個序列,找到m

mm個區間[li

,ri]

[l_i,r_i]

[li​,r

i​]使得這些區間的異或和最大。

先做一遍字首異或,這樣問題就被轉換成找m

mm對l,r

l,rl,

r使得∑lx

or

r\sum l \ xor\ r

∑lxorr

盡量大。

注意到a[l

]xor

a[r]

=a[r

]xor

a[l]

a[l]\ xor\ a[r]=a[r]\ xor\ a[l]

a[l]xo

ra[r

]=a[

r]xo

ra[l

],所以如果選了l,r

l,rl,

r,那麼也會選一遍r,l

r,lr,

l。這樣的話我們可以將詢問次數×

2\times 2

×2,這樣每連續的兩組查詢就是一組相同的(l,

r)(r

,l

)(l,r)(r,l)

(l,r)(

r,l)

。最終答案除以2就行了。

我們維護乙個堆,將每乙個i

ii所對應的a[i

]xor

a[j]

a[i]\ xor\ a[j]

a[i]xo

ra[j

]最大的j

jj扔到堆裡面,每次詢問取堆頂,將下一大的a[i

]xor

a[j]

a[i]\ xor\ a[j]

a[i]xo

ra[j

]扔到堆中。

對於x

xx求y

yy使得a[x

]xor

a[y]

a[x]\ xor\ a[y]

a[x]xo

ra[y

]為第k

kk大顯然是可以用tri

etrie

trie

維護的。每次利用權值來判斷往子樹的左右。

這樣就可以不使用可持久化tri

etrie

trie

來完成這道題了。時間複雜度o(n

log⁡n)

o(n\log n)

o(nlogn)

#include

#include

#include

#include

#define mp make_pair

using

namespace std;

typedef

long

long ll;

const

int n=

500010

,lg=35;

int n,m,tot=

1,trie[n*lg][2

],cnt[n]

,size[n*lg]

;ll a[n]

,ans;

priority_queueint>

> q;

ll read()

void

insert

(ll x)

}ll find

(ll x,

int k)

else

if(trie[p]

[id])}

return ans;

}int

main()

for(

int i=

0;i<=n;i++

) q.

push(mp

(find

(a[i],1

),i));

m*=2

;while

(m--

) cout<2ll;

return0;

}

LG5283 異或粽子

共有 n 個數,選擇 k 個不同的 l,r 區間,使得它們的異或和最大 1 leq n leq 5 times 10 5,k leq 2 times 10 5 先會想到字首異或和,這樣求 l,r 區間異或和只需要用 pre l 1 oplus pre r 以此減少運算次數。然後由於是異或,又會想到 ...

異或粽子 堆 可持久化trie

更新提示 第一次更新 正文 小粽是乙個喜歡吃粽子的好孩子。今天她在家裡自己做起了粽子。小粽面前有 n 種互不相同的粽子餡兒,小粽將它們擺放為了一排,並從左至右編號為 1 到 n。第 i 種餡兒具有乙個非負整數的屬性值 ai。每種餡兒的數量都足夠多,即小粽不 會因為缺少原料而做不出想要的粽子。小粽準備...

洛谷P3760異或和

傳送門啦 傳送門啦 一般這種位運算的題都要把每一位拆開來看,因為位運算每個位的結果這和這一位的數有關。這樣我們用s i 表示a的字首和,即 a 1 a 2 a i 然後我們從這些數二進位制最右位 2 0 開始,按照每一位對答案的貢獻來計算。假設我們現在算到最右位 2 0 並且位於第i個數,我們想要知...