【题解】P5283 异或粽子
【P5283】题解
一:【题意】
- 给定一个序列
- 求 前K大区间异或和 之和
二:【解法】
1.【操作】
做前缀qh,维护可持久化01trie
对于每一个r,建立五元组{x,l,r,L,R},表示[L,R]中,qh[l]^qh[r]最大,值为x
将五元组入最大堆,按照x排序
每次取出top,拆成两个五元组{X,X,r,L,l-1}和{X,X,r,l+1,R}入堆
取K次,累加即为答案
2.【正确性】
显然
3.【时间复杂度】
建树O(32n),入堆O(32(n+2k))=O(32n+64k),总复杂度O(32n+32n+64k)=O(64n+64k)
三:【代码】
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10,Q=34*N;
int a[N],qh[N];
struct node{
int x,l,r,L,R;
const bool operator<(const node b)const{
return x<b.x;
}
};
int ak[Q][2];int rt[N];int cnt;
vector<int> into(int x){
vector<int> q;
while(x){
q.push_back(x%2);
x/=2;
}
while(q.size()<33) q.push_back(0);
reverse(q.begin(),q.end());
return q;
}
void update(int las,int now,vector<int> &q){
//cout<<now<<" "<<cnt<<" ";
for(int i=0;i<q.size();i++){
int x=q[i];
ak[now][!x]=ak[las][!x];
ak[now][x]=++cnt;
now=ak[now][x];
las=ak[las][x];
}
}
int query(int las,int now,vector<int> &q){
int ans=0;
int base=1ll<<32;
for(int i=0;i<q.size();i++){
int x=q[i];
int res=ak[now][!x]-ak[las][!x];
//cout<<x<<" "<<now<<" "<<las<<"\n";
if(res){
ans+=base;
now=ak[now][!x];
las=ak[las][!x];
}
else{
now=ak[now][x];
las=ak[las][x];
}
base/=2;
}
return ans;
}
vector<int> lsh;
int Lsh(int x){
return lower_bound(lsh.begin(),lsh.end(),x)-lsh.begin();
}
vector<int> ttp[N];
int Begin(int tp,int d){
d=Lsh(d);
return *lower_bound(ttp[d].begin(),ttp[d].end(),tp);
}
node Cl(int L,int R,int r){
vector<int> t=into(qh[r]);
int x=query(rt[L-1],rt[R],t);
int l=Begin(L,x^qh[r]);
return {x,l,r,L,R};
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int n,K;cin>>n>>K;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) qh[i]=qh[i-1]^a[i];
//向右偏移
n++;
for(int i=n;i>=2;i--) qh[i]=qh[i-1];qh[1]=0;
//for(int i=1;i<=n;i++) cout<<qh[i]<<" ";cout<<"\n";
for(int i=1;i<=n;i++){
vector<int> t=into(qh[i]);
update(rt[i-1],rt[i]=++cnt,t);
//cout<<rt[i]<<"\n";
lsh.push_back(qh[i]);
}
//for(int i=1;i<=cnt;i++) cout<<i<<" "<<ak[i][0]<<" "<<ak[i][1]<<"\n";cout<<"-----------\n";
sort(lsh.begin(),lsh.end());lsh.erase(unique(lsh.begin(),lsh.end()),lsh.end());
for(int i=1;i<=n;i++) ttp[Lsh(qh[i])].push_back(i);
priority_queue<node> q;
for(int r=2;r<=n;r++) q.push(Cl(1,r-1,r));
int ans=0;
while(K--){
auto tmp=q.top();q.pop();
//cerr<<"-->"<<tmp.x<<" "<<tmp.l<<" "<<tmp.r<<" "<<tmp.L<<" "<<tmp.R<<"\n";
ans+=tmp.x;
if(tmp.L<=tmp.l-1) q.push(Cl(tmp.L,tmp.l-1,tmp.r));
if(tmp.l+1<=tmp.R) q.push(Cl(tmp.l+1,tmp.R,tmp.r));
}
cout<<ans<<"\n";
return 0;
}

浙公网安备 33010602011771号