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

只能说相当套路的一道题目。

对于区间异或和,我们不妨先做一遍区间前缀异或和,记作 sumi,表示 a1ai 的异或和,那么区间 [l,r] 的异或和即可转化为 sumrsuml1,那么我们呢只需对 n+1 个数字进行考虑,⚠️注意还有 sum0=0

既然题目让我们求 k 个粽子的最大值,那么我们不妨先求出第一大,再求出第二大,以此类推最后求出第 k 大,然后将这些全部加起来即可。

总共有 O(n2) 个组合,所以我们绝对不可能将所有的组合进行异或,这时不妨考虑另外一个套路:先搞出一个或几个必须选的,然后用这几个推出其他。

但是我们发现这题还有一个隐藏条件,选出来的 ij 必须满足 ij,这就非常蛋疼,因为这不仅要求找出异或最大的,还要求满足位置上的一定需求。

所以我们不妨将 k×2,这样就可以放松这个条件,毕竟如果选了 (1,2) 就必然会同时选上 (2,1),最后再将答案除以 2 即可。

现在来考虑如何求出必须选的,既然是异或和,那么肯定要用到 01Trie,可以求出对于 x 找出最大的 xsumi 的值,这里不在赘述。对于每个位置,我们找到与其异或最大的,塞进堆里即可。

再来考虑如何通过一个值推出其他。显然,我们可以再先办法对于 x 求出第 k 大的总异或和,这样如果从堆里拿出一个排名为 k 的数,我们在往堆里塞一个排名为 k+1 的数字即可。

代码:

const int N=5e5+10,M=2e7;
int n,k;
LL a[N],sum[N];
int tot=1,tr[M][2],siz[M];
struct node {
LL val; int id,rk;
node(LL a,int b,int c) {
val=a; id=b; rk=c;
}
friend bool operator < (node x,node y) {
return x.val<y.val;
}
};
priority_queue<node> q;
void ins(LL x) {
int nd=1;
for(int i=32;i>=0;i--) {
int p=((x&(1ll<<i))!=0);
siz[nd]++;
if(tr[nd][p]) nd=tr[nd][p];
else {tr[nd][p]=++tot; nd=tot;}
}
siz[nd]++;
}
LL find(LL x,int rk) {
int nd=1; LL ans=0;
for(int i=32;i>=0;i--) {
int p=((x&(1ll<<i))!=0);
if(!tr[nd][!p]) nd=tr[nd][p];
else if(rk<=siz[tr[nd][!p]]) {nd=tr[nd][!p]; ans|=(1ll<<i);}
else {rk-=siz[tr[nd][!p]]; nd=tr[nd][p];}
}
return ans;
}
int main() {
n=read(); k=read(); k<<=1;
ins(0);
for(int i=1;i<=n;i++) {
a[i]=read(); sum[i]=(sum[i-1]^a[i]); ins(sum[i]);
}
for(int i=1;i<=n;i++) {
q.push({find(sum[i],1),i,1});
}
LL ans=0;
q.push({find(sum[0],1),0,1});
while(k) {
auto t=q.top(); q.pop();
ans=ans+t.val;
q.push({find(sum[t.id],t.rk+1),t.id,t.rk+1});
k--;
}
cout<<(ans/2);
return 0;
}
posted @   2017BeiJiang  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示