給出乙個序列,找到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
logn)
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個數,我們想要知...