题目链接:

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

求前$k$大异或区间,可以发现$k$比较小,我们考虑找出每个区间。

为了快速得到一个区间的异或和,将原序列做前缀异或和。

对于每个点作为右端点时,我们维护出与他异或起来最大的左端点并将这组信息用结构体存起来插入堆中。

那么最大值就是堆顶那组(假设右端点为$r$),但考虑到次大值可能出自同一个右端点,所以在弹出堆顶后还需要将以$r$为右端点的次大值插入堆中。

那么如何求出以$r$为右端点的最大值和次大值?

我们对序列每个数为一个版本建可持久化$trie$树,那么最大值就是对于$[1,r]$版本(第一个版本插入的数为$a[0]$)求与一个数异或的最大值。

至于次大值,可以记录求最大值时的版本区间(设为$[l,r]$)及最大值所在序列(或版本)的位置(设为$mid$),在弹出最大值那组信息的同时插入$[l,mid-1]$和$[mid+1,r]$两个区间,分别对这两个区间求最大值即可。

因为需要求具体位置,所以在插入时需要在当前版本插入的一条链的叶子节点记录插入数在原数组的下标,当查询$[l,r]$时,返回$r$版本对应叶子节点记录的信息即可。因为每个版本只插入一个数,所以每个叶子结点记录的就是对应权值的最后一个位置,也就可以保证$r$版本对应叶子节点记录的信息一定在$[l,r]$之间。

那么要求出前$k$大,只需要每次取出堆顶然后将堆顶查询区间分为两部分再插入堆中,重复$k$次即可。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int cnt;
int root[500010];
int n,k;
ll ans;
struct miku
{
int ls,rs,size,id;
}tr[20000010];
ll a[500010],x;
void updata(int &rt,int pre,int dep,ll val,int num)
{
rt=++cnt;
tr[rt].size=tr[pre].size+1;
tr[rt].ls=tr[pre].ls;
tr[rt].rs=tr[pre].rs;
if(dep==0)
{
tr[rt].id=num;
return ;
}
if(val&(1<<(dep-1)))
{
updata(tr[rt].rs,tr[pre].rs,dep-1,val,num);
}
else
{
updata(tr[rt].ls,tr[pre].ls,dep-1,val,num);
}
}
int query(int x,int y,int dep,ll val)
{
if(dep==0)
{
return tr[y].id;
}
if(val&(1<<(dep-1)))
{
if(tr[tr[y].ls].size-tr[tr[x].ls].size>0)
{
return query(tr[x].ls,tr[y].ls,dep-1,val);
}
else
{
return query(tr[x].rs,tr[y].rs,dep-1,val);
}
}
else
{
if(tr[tr[y].rs].size-tr[tr[x].rs].size>0)
{
return query(tr[x].rs,tr[y].rs,dep-1,val);
}
else
{
return query(tr[x].ls,tr[y].ls,dep-1,val);
}
}
}
struct lty
{
int l,r,mid,rt;
ll val;
lty(){}
lty(int L,int R,int RT)
{
l=L,r=R,rt=RT;
mid=query(root[l-1],root[r],32,a[rt]);
val=a[rt]^a[mid-1];
}
bool operator <(lty a)const
{
return val<a.val;
}
};
priority_queue<lty>q;
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%lld",&x);
a[i]=a[i-1]^x;
}
for(int i=1;i<=n;i++)
{
updata(root[i],root[i-1],32,a[i-1],i);
}
for(int i=1;i<=n;i++)
{
q.push(lty(1,i,i));
}
while(k--&&!q.empty())
{
lty now=q.top();
q.pop();
ans+=now.val;
if(now.mid>now.l)
{
q.push(lty(now.l,now.mid-1,now.rt));
}
if(now.mid<now.r)
{
q.push(lty(now.mid+1,now.r,now.rt));
}
}
printf("%lld",ans);
}

还有一种解决方法是记录以$r$为右端点的区间已经取了前$k$大,每次取出堆顶将堆顶记录的$k$加一,查询第$k+1$大的异或区间再插入堆中。这样每组只需要存三个信息相对于上一种方法常数较小。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int cnt;
int root[500010];
int n,k;
ll ans;
struct miku
{
int ls,rs,size;
}tr[20000010];
ll a[500010],x;
void updata(int &rt,int pre,int dep,ll val)
{
rt=++cnt;
tr[rt].size=tr[pre].size+1;
tr[rt].ls=tr[pre].ls;
tr[rt].rs=tr[pre].rs;
if(dep==0)
{
return ;
}
if(val&(1<<(dep-1)))
{
updata(tr[rt].rs,tr[pre].rs,dep-1,val);
}
else
{
updata(tr[rt].ls,tr[pre].ls,dep-1,val);
}
}
ll query(int rt,int dep,ll val,int k)
{
if(dep==0)
{
return 0ll;
}
if(val&(1<<(dep-1)))
{
int res=tr[tr[rt].ls].size;
if(res>=k)
{
return query(tr[rt].ls,dep-1,val,k)+(1ll<<(dep-1));
}
else
{
return query(tr[rt].rs,dep-1,val,k-res);
}
}
else
{
int res=tr[tr[rt].rs].size;
if(res>=k)
{
return query(tr[rt].rs,dep-1,val,k)+(1ll<<(dep-1));
}
else
{
return query(tr[rt].ls,dep-1,val,k-res);
}
}
}
struct lty
{
int k,rt;
ll val;
lty(){}
lty(int K,int RT)
{
k=K,rt=RT;
val=query(root[rt],32,a[rt],k);
}
bool operator <(lty a)const
{
return val<a.val;
}
};
priority_queue<lty>q;
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%lld",&x);
a[i]=a[i-1]^x;
}
for(int i=1;i<=n;i++)
{
updata(root[i],root[i-1],32,a[i-1]);
}
for(int i=1;i<=n;i++)
{
q.push(lty(1,i));
}
while(k--&&!q.empty())
{
lty now=q.top();
q.pop();
ans+=now.val;
q.push(lty(now.k+1,now.rt));
}
printf("%lld",ans);
}

[十二省联考2019]异或粽子——可持久化trie树+堆的更多相关文章

  1. 洛谷.5283.[十二省联考2019]异或粽子(可持久化Trie 堆)

    LOJ 洛谷 考场上都拍上了,8:50才发现我读错了题=-= 两天都读错题...醉惹... \(Solution1\) 先求一遍前缀异或和. 假设左端点是\(i\),那么我们要在\([i,n]\)中找 ...

  2. [十二省联考2019] 异或粽子 - 可持久化Trie,堆

    求 \(n\) 元数列的 \(k\) 个不同的子区间使得各个子区间异或和之和最大. Solution (差点又看错题了) 做个前缀和,于是转化成求序列异或和最大的 \(k\) 个数对 建一棵可持久化 ...

  3. P5283 [十二省联考2019]异或粽子 可持久化01Trie+线段树

    $ \color{#0066ff}{ 题目描述 }$ 小粽是一个喜欢吃粽子的好孩子.今天她在家里自己做起了粽子. 小粽面前有 \(n\) 种互不相同的粽子馅儿,小粽将它们摆放为了一排,并从左至右编号为 ...

  4. 【BZOJ5495】[十二省联考2019]异或粽子(主席树,贪心)

    [BZOJ5495][十二省联考2019]异或粽子(主席树,贪心) 题面 BZOJ 洛谷 题解 这不是送分题吗... 转异或前缀和,构建可持久化\(Trie\). 然后拿一个堆维护每次的最大值,每次如 ...

  5. [十二省联考2019]异或粽子 01trie

    [十二省联考2019]异或粽子 01trie 链接 luogu 思路 首先求前k大的(xo[i]^xo[j])(i<j). 考场上只想到01trie,不怎么会写可持久,就写了n个01trie,和 ...

  6. 【简】题解 P5283 [十二省联考2019]异或粽子

    传送门:P5283 [十二省联考2019]异或粽子 题目大意: 给一个长度为n的数列,找到异或和为前k大的区间,并求出这些区间的异或和的代数和. QWQ: 考试时想到了前缀异或 想到了对每个数按二进制 ...

  7. 【洛谷5283】[十二省联考2019] 异或粽子(可持久化Trie树+堆)

    点此看题面 大致题意: 求前\(k\)大的区间异或和之和. 可持久化\(Trie\)树 之前做过一些可持久化\(Trie\)树题,结果说到底还是主席树. 终于,碰到一道真·可持久化\(Trie\)树的 ...

  8. Luogu P5283 / LOJ3048 【[十二省联考2019]异或粽子】

    联考Day1T1...一个考场上蠢了只想到\(O(n^2)\)复杂度的数据结构题 题目大意: 求前\(k\)大区间异或和的和 题目思路: 真的就是个sb数据结构题,可持久化01Trie能过(开O2). ...

  9. [十二省联考2019]异或粽子(堆+可持久化Trie)

    前置芝士:可持久化Trie & 堆 类似于超级钢琴,我们用堆维护一个四元组\((st, l, r, pos)\)表示以\(st\)为起点,终点在\([l, r]\)内,里面的最大值的位置为\( ...

随机推荐

  1. sublime实现背景透明化

    预览 老司机们就不要吐槽背景图了 实现方法 首先下载插件,直接打包下载zip即可 地址:https://github.com/vhanla/SublimeTextTrans 下载完成后解压到packa ...

  2. CSS宽高背景介绍

    本萌新还未毕业,在一家外包公司干了一个月,因烦恼日常琐事任务,深感外包之坑,以及上班路途艰辛,特转战erp实施,继写日常随笔,望来日屌丝逆袭,走上人生巅峰. 若有错误,请前辈指点迷津,在下谢过. &l ...

  3. Docker for Win10中文乱码问题

    environment:win10  docker+centos7+nginx1.9.9 issue:在docker运行nginx(centos),volume本地html目录挂载到nginx的htm ...

  4. 访问vsts私有nuget

    访问vsts私有nuget Intro 有时候我们可能要自己搭建一个 nuget,如果不对外公开,即包浏览也是需要权限的,那我们应该怎么做才可以支持在哪里都可以正常的还原包呢? 我是在 VSTS(Vi ...

  5. python爬虫实战:利用scrapy,短短50行代码下载整站短视频

    近日,有朋友向我求助一件小事儿,他在一个短视频app上看到一个好玩儿的段子,想下载下来,可死活找不到下载的方法.这忙我得帮,少不得就抓包分析了一下这个app,找到了视频的下载链接,帮他解决了这个小问题 ...

  6. Nagle 算法

    1. Nagel算法        TCP/IP协议中,无论发送多少数据,总是要在数据前面加上协议头,同时,对方接收到数据,也需要发送ACK表示确认.为了尽可能的利用网络带宽,TCP总是希望尽可能的发 ...

  7. C#与SQL Server数据库连接

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  8. SQLServer之创建辅助XML索引

    创建辅助XML索引 使用 CREATE INDEX (Transact-SQL)Transact-SQL DDL 语句可创建辅助 XML 索引并且可指定所需的辅助 XML 索引的类型. 创建辅助 XM ...

  9. 我的第一个python web开发框架(27)——定制ORM(三)

    在上一章中,我们已经创建好ORM的基类了,接下来要做的就是将基类的常用方法一一实现. 首先我们来看看之前项目中,最常见的获取指定主键的记录实体 @get('/api/product/<id:in ...

  10. Windows Service 学习系列(三)——循环引擎 ICycleEngine

    摘要:转载:https://www.cnblogs.com/zhuweisky/archive/2009/09/01/1557792.html#undefined 1.缘起: 有些系统需要每隔一段时间 ...