Soratosorato

洛谷P9533 区间翻转区间异或和 题解

Sorato·2023-08-14 08:51·120 次阅读

洛谷P9533 区间翻转区间异或和 题解

原题:洛谷P9533

一道性质题#

不难发现,区间翻转操作是没有用的(虽然比赛的时候想了好久www)#

首先,区间翻转要想对答案有贡献,一定是下边这种情况:

三个连续的区间:A | B | C

满足:BC=0AC=0

BC 这个灵异区间进行翻转,使 AC 合并到一起,会增加一个灵异区间 AC

但是,如果 BC=0AC=0 ,那么 也有AB=0

因为:若 BC=0AC=0,则 B=CA=C

所以 A=B,即 AB=0

所以翻转前 AB 也是灵异区间,而反转后这个灵异区间就没有了。

所以区间翻转实际上是没用的。#


然后就好写了,统计原数组的灵异区间即可#

原理很简单:维护一个异或前缀和 sum,并用 cnti 记录前缀和为 i 出现的次数。

比如如果 sumi=sumj=x,则区间 [i+1,j] 的异或和为0,即为灵异区间。

且 若也有 sumk=xi<j<k,则区间 [i+1,k] 中共有 2+1=3 个灵异区间([i+1,j],[j+1,k],[i+1,k])。

即若前缀和 x 出现了 m 次,则灵异区间有 1+2+3+...+m=m(m1)/2

我们再用 a 数组记录每种不同的前缀和,遍历 a 数组计算并统计灵异区间数量即可。

还要特殊处理一下 0,很简单,sum 的初值是 0,我们把这个 0 也计入计算即可

Copy
n=read(); cnt[0]=1;a[++tot]=0; while(n--) { sum^=read(); if(!cnt[sum]) a[++tot]=sum; cnt[sum]++; } for(reg int i=1;i<=tot;i=-~i) ans+=cnt[a[i]]*(cnt[a[i]]-1)/2; printf("%lld",ans);
posted @   Sorato  阅读(120)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示
目录