题目大意

有\(n\)(\(n\leq5\times10^5\))个数\(a_1,a_2,...a_n\)(\(a_i\leq 2^{32}-1\))

求区间异或和前\(k(k\leq2\times10^5)\)大之和

题解

考虑二分,找出第\(k\)大异或和是多少

将每个位置上的数变成前缀异或和\(s_i\)后,建出可持久化trie树,第\(i\)个版本由\(0,s_1,s_2,..,s_i\)组成,trie树上每个点维护这个点的子树中有几个数

二分\(x\),判断是否有不超过\(k\)个异或和

发现这样时间复杂度为\(\Theta(n\times log^2 a)\),略多

发现一般情况下在线段树上二分时都不是先二分出一个值再查询,而是在线段树上边走边计算

同理,本题就可以维护\(n\)个位置,即当前走到的第\(i(i\in[1,n])\)个版本的trie树的位置

每次判断当前位放1会不会使大于等于当前值的异或和数量少于\(k\),会就走\(a_i\)当前位异或0的方向,反之就走\(a_i\)当前位异或1的方向

算出第\(k\)大异或和后,直接在trie树中dfs找出大于(注意,不能找等于它的,不然会找多)它的异或和,计入答案,顺便记一共加了几个数

\((k-上一步加的数的个数)\)就是等于第\(k\)大异或和的异或和的个数,把这个计入答案

以上两步中走到的点只有大于第\(k\)大异或和的点和它们的父亲,只有\(\Theta(k\times log\space a)\)

总时间复杂度\(\Theta((n+k)\times log\space a)\)

代码
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
#define maxn 500003
#define maxnd (maxn*33)
#define LL long long
#define int LL
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(LL x)
{
if(x==0){putchar('0'),putchar('\n');return;}
int f=0;char ch[20];
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
return;
}
LL ans,a[maxn],num;;
const int len=31;
int n,k,ch[maxnd][2],val[maxnd],rt[maxn],cntnd,now[maxn],nownum;
void ext(int i)
{
int u,nu=++cntnd;rt[i]=cntnd;
if(i)u=rt[i-1];
else u=0;
dwn(j,len,0)
{
int d=(a[i]&(1ll<<j))>>j;
if(u)val[nu]=val[u]+1,ch[nu][d^1]=ch[u][d^1],u=ch[u][d];
else val[nu]=1;
ch[nu][d]=++cntnd,nu=cntnd;
}
if(u)val[nu]=val[u]+1;
else val[nu]=1;
}
void getans(int u,LL ai,LL xi)
{
if(!ch[u][0]&&!ch[u][1]){if(((LL)ai^(LL)xi)>(LL)num){nownum+=val[u],ans=ans+(LL)((LL)ai^(LL)xi)*val[u];}return;}
if(ch[u][0])getans(ch[u][0],ai,xi<<1);
if(ch[u][1])getans(ch[u][1],ai,xi<<1|1);
return;
}
#define dd(x,y) ((x&(1ll<<y))>>y)
signed main()
{
n=read(),k=read();
rep(i,1,n)a[i]=read()^a[i-1];
rep(i,0,n)ext(i),now[i]=rt[i];
dwn(i,len,0)
{
int tmp=0;
rep(j,1,n)if(now[j]){tmp+=val[ch[now[j]][dd(a[j],i)^1ll]];}
if(tmp+nownum>=k){rep(j,1,n)if(now[j])now[j]=ch[now[j]][dd(a[j],i)^1ll];num=num<<(1ll)|(1ll);}
if(tmp+nownum<k){rep(j,1,n)if(now[j])now[j]=ch[now[j]][dd(a[j],i)];nownum+=tmp;num=num<<(1ll);}
}
nownum=0;
rep(i,1,n)
{
int u=rt[i],vv=0;
dwn(j,len,0)
{
int d=dd(a[i],j),e=dd(num,j);
if(!e&&ch[u][d^1]){getans(ch[u][d^1],a[i],vv<<1|(d^1));}
if(!ch[u][d^e])break;
u=ch[u][d^e],vv=vv<<1|(d^e);
}
}
ans+=(LL)num*(k-nownum);
write(ans);
return 0;
}
/*
3 2
1 2 3
*/
一些感想

sb猎人公会nmsl

并不对劲的loj3048:p5283:[十二省联考]异或粽子的更多相关文章

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

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

  2. LOJ3048 「十二省联考 2019」异或粽子

    题意 题目描述 小粽是一个喜欢吃粽子的好孩子.今天她在家里自己做起了粽子. 小粽面前有 $n$ 种互不相同的粽子馅儿,小粽将它们摆放为了一排,并从左至右编号为 $1$ 到 $n$.第 $i$ 种馅儿具 ...

  3. 洛谷P5283 & LOJ3048:[十二省联考2019]异或粽子——题解

    https://www.luogu.org/problemnew/show/P5283 https://loj.ac/problem/3048 小粽是一个喜欢吃粽子的好孩子.今天她在家里自己做起了粽子 ...

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

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

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

    感觉不是很难的一题,想了0.5h左右(思路歪了,不过想了一个大常数的两只\(\log\)做法233) 然后码+调了1h,除了一个SB的数组开小外基本上也没什么坑点 先讲一个先想到的方法,我们对于这种问 ...

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

    考场上想到了没打完,细节思路还是不是很优,我原先的想法是每一次找完后标记那个点,下次再继续找(并不是这个意思,说不清楚)但实际上和平衡树一样加个大小就很好写了 #include<bits/std ...

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

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

  8. 并不对劲的loj3049:p5284:[十二省联考]字符串问题

    题目大意 给出字符串\(S(|S|\leq2\times10^5)\), \(na(na\leq2\times 10^5)\)个区间\([l_i,r_i]\)表示\(S_{l_i},S_{l_i+1} ...

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

    原题传送门 看见一段的异或和不难想到要做异或前缀和\(s\) 我们便将问题转化成:给定\(n\)个数,求异或值最靠前的\(k\)对之和 我们珂以建一个可持久化01trie,这样我们就珂以求出每个值\( ...

随机推荐

  1. Gvim 和 Opencv编译

    好奇看了一下Gvim编译器:在官网上也有介绍,github上有源码,安装在电脑上,感觉需求不大,记那些命令也太多了.然后编译opencv过程中cmake成功了,但是VS下编译报了很多错,准备不搞这些了 ...

  2. nopCommerce从无到有01-初探nopCommerce

    nopCommerce框架的基本结构: 该结构可以参考DDD(领域驱动设计)模式. (注:上图源自他人文章,具体出处不祥,在此引用,感谢原创) nopcommerce官方地址:http://www.n ...

  3. 使用cacheBuilder时捕获内部指定异常

    由于cacheBuilder是另起线程获取,对call方法中的抛出的异常进行了封装.所以我们在最外层捕获时是无法直接指定异常类型捕获的, 获取异常的原因判断实例类型 public static voi ...

  4. Solidworks安装完成提示failed to load slderresu.dll怎么办

    安装完成出现下面的一系列错误提示   进入到语言包,重新安装中文语言包即可   可以正常打开和运行了                  

  5. vs附加到多个进程调试

    我们用vs调试,通常附加到一个进程进行调试,有时候需要同时附加到多个进程. 例如:同时调试客户端与服务端,我们需要同时附加到客户端与服务端进程. 按F5(执行)键调试,程序只要遇到断点就中断. 按F1 ...

  6. linux c语言 select函数使用方法

    linux c语言 select函数使用方法 表头文件 #i nclude<sys/time.h> #i nclude<sys/types.h> #i nclude<un ...

  7. Allegro封装的制作

    过孔封装的层次分析: 1.阻焊层Solder Mask:又称绿油层,是PCB上的非布线层,用于制成丝网漏印板,将不需要的焊接的地方涂上阻焊剂.由于焊接PCB时焊锡在高温下的流动性,所以必须在不需要焊接 ...

  8. C#基础关键字

    1:override & new public class A { public virtual void Test() { Console.WriteLine("A Test()& ...

  9. unittest相关文档

    文档链接: http://blog.csdn.net/wangst4321/article/details/8454118

  10. xpath 轴,节点之间的关系

    http://www.w3school.com.cn/xpath/xpath_axes.asp http://www.freeformatter.com/xpath-tester.html 测试 轴可 ...