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

传送门

nmd,为什么\(HNOI\)没有这样的送温暖题qwq

所有区间的异或前k大,联想到超级钢琴,然后那题是区间和前k大,所以只要把对应的可持久化线段树改成可持久化\(Trie\)就行了

// luogu-judger-enable-o2
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<set>
#define LL long long
#define db double

using namespace std;
const int N=5e5+10;
LL rd()
{
    LL x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
int s[N*35],ch[N*35][2],rt[N],tt;
void inst(int o1,int o2,LL x)
{
    s[o1]=s[o2]+1;
    for(int i=32;~i;--i)
    {
        int xx=x>>i&1;
        ch[o1][xx]=++tt,ch[o1][xx^1]=ch[o2][xx^1];
        o1=ch[o1][xx],o2=ch[o2][xx];
        s[o1]=s[o2]+1;
    }
}
LL quer(int o,LL x,int k)
{
    LL an=0;
    for(int i=32;~i;--i)
    {
        int xx=x>>i&1;
        if(k<=s[ch[o][xx]]) o=ch[o][xx];
        else an|=1ll<<i,k-=s[ch[o][xx]],o=ch[o][xx^1];
    }
    return an;
}
struct node
{
    int i,j;
    LL x;
    bool operator < (const node &bb) const {return x<bb.x;}
}nw;
priority_queue<node> hp;
int n,k;
LL ans,a[N];

int main()
{
    n=rd(),k=rd();
    for(int i=1;i<=n;++i)
    {
        a[i]=a[i-1]^rd();
        inst(rt[i]=++tt,rt[i-1],a[i-1]);
        hp.push((node){i,i,quer(rt[i],a[i],i)});
    }
    while(!hp.empty()&&k--)
    {
        nw=hp.top();
        hp.pop();
        ans+=nw.x;
        if(nw.j>1) --nw.j,nw.x=quer(rt[nw.i],a[nw.i],nw.j),hp.push(nw);
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/smyjr/p/10699883.html