码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2020-02-08 18:04:02      阅读:121      评论:0      收藏:0      [点我收藏+]

标签:trie树   运算符   com   好孩子   lld   正整数   data   现在   持久   

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

Description

题目描述

小粽是一个喜欢吃粽子的好孩子。今天她在家里自己做起了粽子。

小粽面前有 nn 种互不相同的粽子馅儿,小粽将它们摆放为了一排,并从左至右编号为 11 到 nn。第 ii 种馅儿具有一个非负整数的属性值 a_iai?。每种馅儿的数量都足够多,即小粽不会因为缺少原料而做不出想要的粽子。小粽准备用这些馅儿来做出 kk 个粽子。

小粽的做法是:选两个整数数 ll, rr,满足 1 \leqslant l \leqslant r \leqslant n1?l?r?n,将编号在 [l, r][l,r] 范围内的所有馅儿混合做成一个粽子,所得的粽子的美味度为这些粽子的属性值的异或和。(异或就是我们常说的 xor 运算,即 C/C++ 中的 ˆ 运算符或 Pascal 中的 xor 运算符)

小粽想品尝不同口味的粽子,因此它不希望用同样的馅儿的集合做出一个以上的 粽子。

小粽希望她做出的所有粽子的美味度之和最大。请你帮她求出这个值吧!

输入格式

第一行两个正整数 nn, kk,表示馅儿的数量,以及小粽打算做出的粽子的数量。

接下来一行为 nn 个非负整数,第 ii 个数为 a_iai?,表示第 ii 个粽子的属性值。 对于所有的输入数据都满足:1 \leqslant n \leqslant 5 \times 10^51?n?5×105, 1 \leqslant k \leqslant \min\left\{\frac{n(n-1)}{2},2 \times 10^{5}\right\}1?k?min{2n(n1)?,2×105}, 0 \leqslant a_i \leqslant 4 294 967 2950?ai??4294967295。

输出格式

输出一行一个整数,表示小粽可以做出的粽子的美味度之和的最大值。

Solution

想来一年前去体验省选时我还是个暴力都没拿到分的蒟蒻。。。

现在已经可以独立做出来啦  开心!

年年岁岁题相似,岁岁年年人不同

正文:

设a[ i ]:1~i 的异或和

对于每个 i ,建立一颗trie树储存 1~i 的 a;

在这棵trie树上搜索与a[i]异或所得值最大的一个数,并边找边删去它,把这个所得值和i加入大根堆中

1~n扫完后开始在堆中找最大的k个数,每弹出一个堆顶要再在它的trie树里找到并删去最大值,再加入堆中

可是这样数组太大,于是用可持久化优化,记得加数和删树时都要重建树,不然会对共用节点的其他树造成影响

Code

#include <cstdio>
#include <cstdlib>
#include <queue>
#define ll long long
using namespace std;
const int N=1e6+10;
struct node
{
    int ch[2],sum;
}f[N*80];
int n,k,rt[N],tot,cnt[N];
ll a[N],ans,an=1;
void build(int x,int y,int t,ll pos)
{
    if(t<0) return ;
    int wh=(pos>>t)&1;
    f[x].ch[!wh]=f[y].ch[!wh];
    f[x].ch[wh]=++tot;
    f[f[x].ch[wh]].sum=f[f[y].ch[wh]].sum+1;
    build(f[x].ch[wh],f[y].ch[wh],t-1,pos);
}
struct mode
{
    int id;
    ll v;
    bool operator <(const mode &o)const
    {
        return v<o.v;
    }
};
priority_queue <mode> q;
ll get(int x,int y,int t,ll pos)
{
    if(t<0) return 0;
    int wh=(pos>>t)&1;
    int yy=f[y].ch[!wh],zz=f[y].ch[wh];
    if(f[yy].sum>0)
    {
        f[x].ch[wh]=zz;
        f[x].ch[!wh]=++tot;
        f[tot].sum=f[yy].sum-1;
        return (an<<t)+get(f[x].ch[!wh],yy,t-1,pos);
    }
    else
    {
        f[x].ch[!wh]=yy;
        f[x].ch[wh]=++tot;
        f[tot].sum=f[zz].sum-1;
        return get(f[x].ch[wh],zz,t-1,pos);
    }
}
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        a[i]^=a[i-1];
        rt[i]=++tot;
        build(rt[i],rt[i-1],32,a[i-1]);
    }
    for(int i=1;i<=n;i++)
    {
        cnt[i]++;
        int nw=++tot;
        ll xx=get(nw,rt[i],32,a[i]);
        rt[i]=nw;
        q.push((mode){i,xx});
    }
    while(k--)
    {
        mode tp=q.top();
        q.pop();
        ans+=tp.v;
        if(++cnt[tp.id]<=tp.id)
        {
            int nw=++tot;
            ll xx=get(nw,rt[tp.id],32,a[tp.id]);
            rt[tp.id]=nw;
            q.push((mode){tp.id,xx});
        }
    }
    printf("%lld\n",ans);
    return 0;
}

 

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

标签:trie树   运算符   com   好孩子   lld   正整数   data   现在   持久   

原文地址:https://www.cnblogs.com/hsez-cyx/p/12283811.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!