P5283 [十二省联考2019]异或粽子 题解
首先求出原数组的前缀 xor
数组 \(s\),这样相当于要在其中找两个值使其 xor
起来最大。
维护一个堆,里面有 \(n\) 个元素,分别为当前与 \(s_i\) 异或最大的数。每次取出来一个就把与当前这个 \(s_i\) 异或次大的数放进去,以此类推即可。使用类似线段树二分的方法可以做到在trie树上求与某个数异或第 \(k\) 大的数。
要注意,这样的话每一段会被问到两次,所以考虑再记一个当前这个 \(s_i\) 与哪个 \(s_j\) 的异或值最大,每次把 \(i,j\) 都向后推。还要注意当 \(s\) 值相同的时候要定好顺序。复杂度是 \(O((n+k)\log v)\)。
点击查看代码
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#define mp std::make_pair
#define fi first
#define se second
typedef long long ll;
typedef std::pair<ll,int> pii;
inline ll rd(){
ll res=0;char c=getchar();
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())res=(res<<1)+(res<<3)+(c-'0');
return res;
}
const int N=5e5+13,M=32+13;
const ll INF=0x3f3f3f3f3f3f3f3fll;
struct Trie{
int ch[N*M][2],siz[N*M],tot,a[M];
std::vector<int> num[N*M];
Trie(){tot=1;}
inline void insert(ll x,int i){
for(int i=0;i<32;++i) a[i]=(x&1),x>>=1;
int p=1;
for(int i=31;i>=0;--i){
if(!ch[p][a[i]]) ch[p][a[i]]=++tot;
p=ch[p][a[i]],++siz[p];
}
num[p].push_back(i);
}
inline pii query(ll x,int k){
for(int i=0;i<32;++i) a[i]=(x&1),x>>=1;
int p=1;ll res=0;
for(int i=31;i>=0;--i){
if(siz[ch[p][a[i]^1]]>=k) res|=(1ll<<i),p=ch[p][a[i]^1];
else{
k-=siz[ch[p][a[i]^1]];
p=ch[p][a[i]];
}
}
return mp(res,num[p][k-1]);
}
}T;
struct Node{
ll x;int id1,id2,flag;
bool operator <(const Node &a)const{
if(x==a.x) return id2>a.id2;
return x<a.x;
}
};
std::priority_queue<Node> s;
int n,m,b[N];
ll a[N];
int main(){
//freopen("2.in","r",stdin);
//freopen("P5283.out","w",stdout);
n=rd(),m=rd();
for(int i=1;i<=n;++i) a[i]=rd()^a[i-1],T.insert(a[i],i);
for(int i=0;i<=n;++i){
pii now=T.query(a[i],b[i]=1);
s.push((Node){now.fi,now.se,i,b[i]});
}
ll ans=0;
while(m--&&!s.empty()){
ll tmp=s.top().x;
int i=s.top().id1,j=s.top().id2,flag=s.top().flag;s.pop();
if(flag!=b[j]){++m;continue;}
ans+=tmp;
b[i]++;
if(b[i]<=n){
pii now=T.query(a[i],b[i]);
s.push((Node){now.fi,now.se,i,b[i]});
}
if(i==j) continue;
b[j]++;
if(b[j]<=n){
pii now=T.query(a[j],b[j]);
s.push((Node){now.fi,now.se,j,b[j]});
}
}
printf("%lld\n",ans);
return 0;
}