Luogu P5283 [十二省联考2019]异或粽子
感觉不是很难的一题,想了0.5h左右(思路歪了,不过想了一个大常数的两只\(\log\)做法233)
然后码+调了1h,除了一个SB的数组开小外基本上也没什么坑点
先讲一个先想到的方法,我们对于这种问题显然可以二分第\(k\)大,然后验证有多少个值小于等于它
然后考虑怎么判断,我们建一棵0/1Trie,然后枚举一个右端点,每次把整个Trie异或上这个点的权值
具体实现的话就是不断向下走的过程,当这一位为\(1\)时交换左右子树即可
然后相当于查小于等于一个数的数个数以及和,直接Trie上节点维护一下即可
这样是\(n \log \max{a_i}\log n\)的,由于\(a_i\)值域比较大而且直接跑满了,因此可能无法通过此题
然后慢慢就想到一种诡异的做法,先记录一下前缀异或和,然后考虑算出每个点为右端点时的最大值和左端点
这样有一个好处,我们每次用堆维护这\(n\)的点为右端点是答案的最大值,那么直接算出前\(k\)大即可
那么考虑如何计算,首先如果不考虑删除的话是挺简单的,我们建一棵可持久化0/1Trie,然后每个点在对应的Trie上找一个数和它异或值最大即可(类似于普通0/1Trie)
那么问题来了,我们统计完一个点的值时怎么删除能,可持久化数据结构一旦删除不是就全乱了么
其实不一定,由于这里只删一条已添加过的链,因此有一种奇妙的方法
我们记录左端点后找到右端点此时的Trie根节点编号,然后新开一个可持久化0/1Trie,然后直接在此时的版本上删去左端点对应的链即可
由于堆只需要取\(k\)次值,因此最多多产生\(k\)个版本,所以这部分的复杂度为\((n+k)\log \max{a_i}\)
然后加上堆的\(k\log n\)之后还是轻松通过此题,不过注意版本的数组大小要开大
CODE
#include<cstdio>
#include<cctype>
#include<queue>
#define RI register int
#define CI const int&
#define Tp template <typename T>
using namespace std;
typedef unsigned int u32;
const int N=5e5+5,R=32;
struct data
{
u32 val; int id;
inline data(const u32& Val=0,CI Id=0)
{
val=Val; id=Id;
}
friend inline bool operator < (const data& A,const data& B)
{
return A.val<B.val;
}
}; priority_queue <data> hp; long long ans;
int n,k,rt[N<<1],pos[N],cur; u32 a[N],pfx[N],ret;
class FileInputOutput
{
private:
static const int S=1<<21;
#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
char Fin[S],*A,*B;
public:
Tp inline void read(T& x)
{
x=0; char ch; while (!isdigit(ch=tc()));
while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
}
#undef tc
}F;
class Segment_Tree
{
private:
struct segment
{
int ch[2],size;
}node[N*(R+1)<<1]; int tot;
public:
#define lc(x) node[x].ch[0]
#define rc(x) node[x].ch[1]
#define S(x) node[x].size
inline void build(int& now,CI dep=R-1)
{
now=++tot; S(now)=1; if (!~dep) return; build(lc(now),dep-1);
}
inline void insert(CI lst,int& now,const u32& num,CI mv,CI dep=R-1)
{
now=++tot; node[now]=node[lst]; S(now)+=mv; if (!~dep) return;
if ((num>>dep)&1u) insert(rc(lst),rc(now),num,mv,dep-1);
else insert(lc(lst),lc(now),num,mv,dep-1);
}
inline void query(CI now,const u32& num,CI dep=R-1)
{
if (!~dep) return; if (S(node[now].ch[((num>>dep)&1)^1]))
ret|=1u<<dep,query(node[now].ch[((num>>dep)&1)^1],num,dep-1);
else query(node[now].ch[(num>>dep)&1],num,dep-1);
}
#undef lc
#undef rc
#undef S
}SEG;
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
RI i; for (F.read(n),F.read(k),i=1;i<=n;++i) F.read(a[i]);
for (SEG.build(rt[0]),i=1;i<=n;++i)
{
pfx[i]=pfx[i-1]^a[i]; SEG.insert(rt[i-1],rt[i],pfx[i],1);
ret=0; SEG.query(rt[pos[i]=i],pfx[i]); hp.push(data(ret,i));
}
for (cur=n;k;--k)
{
data nw=hp.top(); hp.pop(); ans+=nw.val;
SEG.insert(rt[pos[nw.id]],rt[++cur],nw.val^pfx[nw.id],-1);
ret=0; SEG.query(rt[pos[nw.id]=cur],pfx[nw.id]); hp.push(data(ret,nw.id));
}
return printf("%lld",ans),0;
}
Luogu P5283 [十二省联考2019]异或粽子的更多相关文章
- 【题解】Luogu P5283 [十二省联考2019]异或粽子
原题传送门 看见一段的异或和不难想到要做异或前缀和\(s\) 我们便将问题转化成:给定\(n\)个数,求异或值最靠前的\(k\)对之和 我们珂以建一个可持久化01trie,这样我们就珂以求出每个值\( ...
- 【简】题解 P5283 [十二省联考2019]异或粽子
传送门:P5283 [十二省联考2019]异或粽子 题目大意: 给一个长度为n的数列,找到异或和为前k大的区间,并求出这些区间的异或和的代数和. QWQ: 考试时想到了前缀异或 想到了对每个数按二进制 ...
- P5283 [十二省联考2019]异或粽子
考场上想到了没打完,细节思路还是不是很优,我原先的想法是每一次找完后标记那个点,下次再继续找(并不是这个意思,说不清楚)但实际上和平衡树一样加个大小就很好写了 #include<bits/std ...
- P5283 [十二省联考2019]异或粽子 可持久化01Trie+线段树
$ \color{#0066ff}{ 题目描述 }$ 小粽是一个喜欢吃粽子的好孩子.今天她在家里自己做起了粽子. 小粽面前有 \(n\) 种互不相同的粽子馅儿,小粽将它们摆放为了一排,并从左至右编号为 ...
- [十二省联考2019]异或粽子 01trie
[十二省联考2019]异或粽子 01trie 链接 luogu 思路 首先求前k大的(xo[i]^xo[j])(i<j). 考场上只想到01trie,不怎么会写可持久,就写了n个01trie,和 ...
- [十二省联考2019]异或粽子——可持久化trie树+堆
题目链接: [十二省联考2019]异或粽子 求前$k$大异或区间,可以发现$k$比较小,我们考虑找出每个区间. 为了快速得到一个区间的异或和,将原序列做前缀异或和. 对于每个点作为右端点时,我们维护出 ...
- 【BZOJ5495】[十二省联考2019]异或粽子(主席树,贪心)
[BZOJ5495][十二省联考2019]异或粽子(主席树,贪心) 题面 BZOJ 洛谷 题解 这不是送分题吗... 转异或前缀和,构建可持久化\(Trie\). 然后拿一个堆维护每次的最大值,每次如 ...
- Luogu P5283 / LOJ3048 【[十二省联考2019]异或粽子】
联考Day1T1...一个考场上蠢了只想到\(O(n^2)\)复杂度的数据结构题 题目大意: 求前\(k\)大区间异或和的和 题目思路: 真的就是个sb数据结构题,可持久化01Trie能过(开O2). ...
- 洛谷P5283 & LOJ3048:[十二省联考2019]异或粽子——题解
https://www.luogu.org/problemnew/show/P5283 https://loj.ac/problem/3048 小粽是一个喜欢吃粽子的好孩子.今天她在家里自己做起了粽子 ...
随机推荐
- Java数据结构和算法 - 堆
堆的介绍 Q: 什么是堆? A: 这里的“堆”是指一种特殊的二叉树,不要和Java.C/C++等编程语言里的“堆”混淆,后者指的是程序员用new能得到的计算机内存的可用部分 A: 堆是有如下特点的二叉 ...
- hadoop rpc协议客户端与服务端的交互流程
尽管这里是hadoop的rpc服务,但是hadoop还是做到了一次连接仅有一次认证.具体的流程待我慢慢道来. 客户端:这里我们假设ConnectionId对应的Connection并不存在.在调用ge ...
- 接口测试---Python数据处理需要注意的细节
一.json模块中的dumps方法 请求接口时params肯定是dict类型的,就是这种{"A":"B"},因为需要传json格式的参数到服务端,但是为了降低c ...
- WebApiClient与Asp.net core DI的结合
1 WebApiClient 一款基于HttpClient封装,只需要定义c#接口并修饰相关特性,即可异步调用远程http接口的客户端库 WebApiClient WebApiClient.Exten ...
- #6 判断一个数是否为2的n次方
「ALBB面试题」 [题目] 如何判断一个数是否为2的n次方 [题目分析] 看到这种题,相信大家第一反应就是循环除2,这样做肯定是可以得出结果的:但是这种做法无疑大大增加了计算机的运行时间,一个非常大 ...
- (摘)C#生成随机数的三种方法
随机数的定义为:产生的所有数字毫无关系. 在实际应用中很多地方会用到随机数,比如需要生成唯一的订单号. 在C#中获取随机数有三种方法: 一.Random 类 Random类默认的无参构造函数可以根据当 ...
- C#的一些获取时间的例子
从周一到周日的顺序,获取排序数值: int i = DateTime.Now.DayOfWeek - DayOfWeek.Monday; if (i == -1) i = 6; 获取某日起,星期一日期 ...
- js + 加号 报错,IIS 配置
一.问题描述: 1开发环境完全没有问题: 2 build 后生成的js脚本,带有+号. 程序发布到IIS后,带加+号js脚本报错. 二.解决方案 1 修改build规则,让它不产生特殊符号. 能力有 ...
- C# 创建、更改Excel命名区域(NamedRange)
创建命名区域是指给选定的某个单元格或多个单元格区域设置名称,目的是方便我们在文件中的其他地方对该单元格区域进行引用能够简化公式引用或者方便数据管理.下面记录了具体的C#示例代码.这里创建命名区域分为了 ...
- css 半圆效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...