【题解】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;
}
posted @ 2025-12-15 16:07  Ming3398  阅读(0)  评论(0)    收藏  举报