P5283 [十二省联考2019]异或粽子

思路

类似Argus那题的思路,每个维护当前位置和第x大的值,取出堆顶后放入下一个,就是当前位置的第x+1大的值

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define int long long 
using namespace std;
const int MAXlog = 33;
struct Node{
    int son[2],sz;
}Trie[500100*50];
int root[500100],Nodecnt;
void insert(int d,int val,int &o){
    ++Nodecnt;
    Trie[Nodecnt]=Trie[o];
    o=Nodecnt;
    Trie[o].sz++;
    if(d>=0)
        insert(d-1,val,Trie[o].son[(val>>d)&1]);
}
int query(int root,int val,int d,int k){
    if(d==-1)
        return 0;
    if(Trie[Trie[root].son[!((val>>d)&1)]].sz>=k)
        return (1LL<<d)+query(Trie[root].son[!((val>>d)&1)],val,d-1,k);
    else
        return query(Trie[root].son[((val>>d)&1)],val,d-1,k-(Trie[Trie[root].son[!((val>>d)&1)]].sz));
}
struct QNode{
    int kx,pos,val;
    bool operator < (const QNode &b)const {
        return val<b.val;
    }
};
priority_queue<QNode> q;
int sumx[500100],x[500100],n,k;
signed main(){
    // freopen("test.in","r",stdin);
    // freopen("test.out","w",stdout);
    scanf("%lld %lld",&n,&k);
    insert(MAXlog,0,root[0]);
    for(int i=1;i<=n;i++){
        scanf("%lld",&x[i]);
        sumx[i]=sumx[i-1]^x[i];
        // printf("%lld ",sumx[i]);
        root[i]=root[i-1];
        insert(MAXlog,sumx[i],root[i]);
    }
    for(int i=1;i<=n;i++){
        // int x;
        q.push((QNode){1,i,query(root[i-1],sumx[i],MAXlog,1)});
        // printf("push:%lld\n",x);
    }   
    int ans=0;
    for(int i=1LL;i<=k;i++){
        QNode x=q.top();
        q.pop();
        ans+=x.val;
        q.push((QNode){x.kx+1,x.pos,query(root[x.pos-1],sumx[x.pos],MAXlog,x.kx+1)});
    }
    printf("%lld\n",ans);
    return 0;
}
posted @ 2019-04-18 17:32  dreagonm  阅读(159)  评论(0编辑  收藏  举报