题目链接:

[十二省联考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. Python二次编码、小数据池之心照神交

    二次编码.解码.小数据池: encode(str:编码):参数编码方式,返回字节码. str_1 = "编码" str_2 = str_1.encode("utf-8&q ...

  2. 【原】无脑操作:eclipse创建maven工程时,如何修改默认JDK版本?

    问题描述:eclipse建立maven项目时,JDK版本默认是1.5,想创建时默认版本设置为1.8,如何修改? 解决方案: 找到本机maven仓库存放位置,比如:${user.home}/.m2/路径 ...

  3. phpstorm设置编码格式

    phpstorm设置编码格式 默认: utf-8格式 设置方法: file -> settings -> Editor -> file encodng -> project e ...

  4. 两种动态SQL

    参考:http://www.cnblogs.com/wanyuan8/archive/2011/11/09/2243483.htmlhttp://www.cnblogs.com/xbf321/arch ...

  5. Python面试笔记一

    目录 一.MySQL(30题) 二.django(15题) 三.Python部分(46题) 四.RESTful API设计指南(7题) 五.补充 一.MySQL(30题) 1.mysql如何做分页 m ...

  6. spring异步执行报异常No qualifying bean of type 'org.springframework.core.task.TaskExecutor' available

    最近观察项目运行日志的时候突然发现了一个异常, [2018-04-03 10:49:07] 100.0.1.246 http-nio-8080-exec-9 DEBUG org.springframe ...

  7. 网络流问题 P2763 试题库问题

    题目描述 «问题描述: 假设一个试题库中有n道试题.每道试题都标明了所属类别.同一道题可能有多个类别属性.现要从题库中抽取m 道题组成试卷.并要求试卷包含指定类型的试题.试设计一个满足要求的组卷算法. ...

  8. 需求规格说明书(SRS)特点

    需求说明书的7大特征: 完整性 正确性 可行性 必要性 划分优先级 无二义性 可验证性 每条需求规格说明书的4大特点: 完整性 一致性 可修改性 可跟踪性 需求管理就是一种获取.组织并记录系统需求的系 ...

  9. zabbix源码安装 令人窒息的操作

    一.简介 zabbix-server主要分为2部分: zabbix程序 程序根据客户端的监控项,从客户端获取数据并写入到数据库,再根据触发器/动作等配置进行操作. 展示页面 使用php编写,php脚本 ...

  10. leetcode 136. Single Number 、 137. Single Number II 、 260. Single Number III(剑指offer40 数组中只出现一次的数字)

    136. Single Number 除了一个数字,其他数字都出现了两遍. 用亦或解决,亦或的特点:1.相同的数结果为0,不同的数结果为1 2.与自己亦或为0,与0亦或为原来的数 class Solu ...