[十二省联考2019] 异或粽子 解题报告 (可持久化Trie+堆)

Posted xxzh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[十二省联考2019] 异或粽子 解题报告 (可持久化Trie+堆)相关的知识,希望对你有一定的参考价值。

interlinkage:

https://www.luogu.org/problemnew/show/P5283

description:

技术图片

solution:

  • 显然有$O(n^2)$的做法,前缀和优化一下即可
  • 正解做法是先确定一个右端点$r$,找到最优的$l$使得该区间的异或和最大,这个可以用可持久化$Trie$实现。不懂的话可以在我的博客里搜索
  • 对每个点取出来后把答案放进一个堆里,显然当前的堆顶一定会对答案产生贡献
  • 然后我们考虑每次取出的右端点,它依旧可能产生贡献。即上一次取的最优的$l$把原来的区间割裂成了两部分,把这两部分的最优解算出来再次放进堆里就好
  • 这样取出$k$个就一定是最优的$k$个了

code:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;

const int N=5e5+15;
int n,k,cnt;
int rt[N];
ll a[N];
struct Trie
{
    int ch[2];
    int id,siz;
}t[N*40];
inline ll read()
{
    char ch=getchar();ll s=0,f=1;
    while (ch<0||ch>9) {if (ch==-) f=-1;ch=getchar();}
    while (ch>=0&&ch<=9) {s=(s<<3)+(s<<1)+ch-0;ch=getchar();}
    return s*f;
}
void ins(int &now,int pre,int bit,int id,ll val)
{
    now=++cnt;t[now]=t[pre];t[now].siz++;
    if (bit==-1)
    {
        t[now].id=id;
        return;
    }
    if ((val>>bit)&1) ins(t[now].ch[1],t[pre].ch[1],bit-1,id,val);
    else ins(t[now].ch[0],t[pre].ch[0],bit-1,id,val);
}
int query(int k1,int k2,int bit,ll val)
{
    if (bit==-1) return t[k2].id;
    int d=(val>>bit)&1;
    if (t[t[k2].ch[d^1]].siz-t[t[k1].ch[d^1]].siz>0) return query(t[k1].ch[d^1],t[k2].ch[d^1],bit-1,val);
    return query(t[k1].ch[d],t[k2].ch[d],bit-1,val);
}
struct node 
{
    int l,r,x,id;ll val;
    node(int _l=0,int _r=0,int _x=0)
    {
        l=_l;r=_r;x=_x;
        id=query(rt[l-1],rt[r],31,a[x]);
        val=a[x]^a[id-1];
    }
};
bool operator < (const node &a,const node &b) {return a.val<b.val;}
priority_queue<node> Q;
int main()
{
    freopen("xor.in","r",stdin);
    freopen("xor.out","w",stdout);
    n=read();k=read();
    for (int i=1;i<=n;i++) a[i]=a[i-1]^read();
    for (int i=1;i<=n;i++) ins(rt[i],rt[i-1],31,i,a[i-1]);
    for (int i=1;i<=n;i++) Q.push(node(1,i,i));
    ll ans=0;
    while (k--)
    {
        node u=Q.top();Q.pop();
        ans+=u.val;
        if (u.l<u.id) Q.push(node(u.l,u.id-1,u.x));
        if (u.r>u.id) Q.push(node(u.id+1,u.r,u.x));
    }
    printf("%lld
",ans);
    return 0;
}

以上是关于[十二省联考2019] 异或粽子 解题报告 (可持久化Trie+堆)的主要内容,如果未能解决你的问题,请参考以下文章

[十二省联考2019]异或粽子(可持久化tire,堆)

#4349. 「十二省联考 2019」异或粽子

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

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

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

P5283 [十二省联考2019]异或粽子 可持久化字典树