题面

原题题面

转化方便版题意:

n

n

n 堆石子,第

i

i

i 堆有

c

i

[

1

,

m

]

c_i\in [1,m]

ci​∈[1,m] 个石子,有

q

q

q 次询问,每次询问给出

L

i

,

R

i

L_i,R_i

Li​,Ri​ ,先把

c

i

∉

[

L

i

,

R

i

]

c_i\not\in [L_i,R_i]

ci​​∈[Li​,Ri​] 的石堆都扔掉,然后把每堆石子减少

L

i

L_i

Li​ 个,最后用剩下的若干堆石子做

N

i

m

Nim

Nim 游戏,先手必胜输出

A

\tt A

A ,后手必胜输出

B

\tt B

B 。

1

n

,

m

,

q

2

1

0

5

1\leq n,m,q\leq2\cdot10^5

1≤n,m,q≤2⋅105.

题解

官方题解,是

O

(

N

N

log

N

)

O(N\sqrt{N\log N})

O(NNlogN

​) 的做法。

对每个询问暴力求解,是

O

(

N

2

)

O(N^2)

O(N2) 的。或者,如果记录每一种

c

i

c_i

ci​ 值的出现次数的话,也可以是

O

(

N

M

)

O(NM)

O(NM) 的。后者可以优化:

c

i

c_i

ci​ 的二进制表示有

18

\tt18

18 位,我们把前面九位和后面九位分开算,这样,分别就只有

2

9

=

512

2^9=512

29=512 种取值,也就是

M

\sqrt{M}

M

​ 种取值了,这就增加了暴力的可能性。同时,只管前九位和后九位都是能比较方便地处理加减法的,因此这样刚好是可行的,要是分成前六位、中六位、后六位就及其不好做了。

但是,处理后九位数字还是比较麻烦的。而且,这个时间复杂度也不优。

不如看看下面又易懂又好写还在时间复杂度上暴踩官解的做法。


真是妙蛙种子吃着妙脆角,妙进了米奇妙妙屋,妙到家了

真的就不能每一位分开来做了吗?

加减法固然会对二进制表示产生不好计量的影响,但是我们有这么一条很容易发现的结论:

  • A

    <

    2

    k

    A<2^k

    A<2k ,则

    A

    +

    2

    k

    =

    A

    x

    o

    r

    2

    k

    A+2^k=A~xor~2^k

    A+2k=A xor 2k

这种情况下,加法是等同于异或的!

那我们不妨就想个办法,能不能把减法变成加法,然后把要加的部分按位拆分开来,利用上面的结论一步一步异或进去呢?

有!那就是倍增。倍增可以把减法换成加法,而且不难发现,倍增刚好是从高位往低位考虑的,前面要加的数的 lowbit 一定比后面的数都大。

我们定义

f

[

i

]

[

j

]

f[i][j]

f[i][j] 为询问

L

=

i

,

R

=

i

+

2

j

1

L=i,R=i+2^j-1

L=i,R=i+2j−1 时的答案,不难发现

f

[

i

]

[

0

]

=

0

f[i][0]=0

f[i][0]=0。

计算

f

[

i

]

[

j

]

f[i][j]

f[i][j] 的时候,先异或上

f

[

i

]

[

j

1

]

f[i][j-1]

f[i][j−1] ,然后由于

f

[

i

+

2

j

1

]

[

j

1

]

f[i+2^{j-1}][j-1]

f[i+2j−1][j−1] 中的每堆石子个数

<

2

j

1

< 2^{j-1}

<2j−1 ,我们把这些石堆加上

2

j

1

2^{j-1}

2j−1 时,等价于异或

2

j

1

2^{j-1}

2j−1,因此我们只需要再知道

[

i

+

2

j

1

,

i

+

2

j

1

]

[i+2^{j-1},i+2^j-1]

[i+2j−1,i+2j−1] 区间之内石堆的个数,就可以转移了。令

c

t

[

i

]

[

j

]

ct[i][j]

ct[i][j] 表示

c

i

[

i

,

i

+

2

j

1

]

c_i\in[i,i+2^j-1]

ci​∈[i,i+2j−1] 的石堆的个数,则:

f

[

i

]

[

j

]

=

f

[

i

]

[

j

1

]

x

o

r

f

[

i

+

2

j

1

]

[

j

1

]

x

o

r

(

2

j

1

(

c

t

[

i

+

2

j

1

]

[

j

1

]

%

2

)

)

c

t

[

i

]

[

j

]

=

c

t

[

i

]

[

j

1

]

+

c

t

[

i

+

2

j

1

]

[

j

1

]

f[i][j]=f[i][j-1]~{\tt xor}~f[i+2^{j-1}][j-1]~{\tt xor}~\Big( 2^{j-1}\cdot(ct[i+2^{j-1}][j-1]\,\%\,2) \Big)\\ ct[i][j]=ct[i][j-1]+ct[i+2^{j-1}][j-1]

f[i][j]=f[i][j−1] xor f[i+2j−1][j−1] xor (2j−1⋅(ct[i+2j−1][j−1]%2))ct[i][j]=ct[i][j−1]+ct[i+2j−1][j−1]

询问的时候,类似的。由于是倍增,每次访问到的

f

[

i

]

[

j

]

f[i][j]

f[i][j] 的

j

j

j 都会变小,也就是说它所代表的这个区间内的石堆

c

i

c_i

ci​ 都小于先前的

2

j

2^j

2j ,都可以把加法换成异或,再通过

c

t

[

i

]

[

j

]

ct[i][j]

ct[i][j] 补到

f

[

i

]

[

j

]

f[i][j]

f[i][j] 中。

代码也很好理解,基本是标准的预处理倍增。时间复杂度只有

O

(

N

log

N

)

O(N\log N)

O(NlogN) 。

CODE

比解说还短的倍增代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 200005
#define ENDL putchar('\n')
#define LL long long
#define DB double
#define lowbit(x) ((-x) & (x))
LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
int n,m,i,j,s,o,k;
int c[MAXN],dp[MAXN][20],ct[MAXN][20];
int main() {
// Input
n = read();m = read();
for(int i = 1;i <= n;i ++)
c[i] = read(),ct[c[i]][0] ++; // Init
for(int i = m;i > 0;i --) {
for(int j = 1;i+(1<<j)-1 <= m;j ++) {
ct[i][j] = ct[i][j-1] + ct[i+(1<<(j-1))][j-1];
dp[i][j] = dp[i][j-1] ^ dp[i+(1<<(j-1))][j-1] ^ ((ct[i+(1<<(j-1))][j-1] & 1) ? (1<<(j-1)):0);
}
} // Query
int q = read();
while(q --) {
s = read();o = read();
int xr = 0,as = 0;
for(int j = 18;j >= 0;j --) {
if(s+(1<<j)-1 <= o) {
as ^= dp[s][j]^((ct[s][j] & 1) ? xr:0);
xr ^= (1<<j); s += (1<<j);
}
}
printf(as ? "A":"B");
}
return 0;
}

CF1511G Chips on a Board (倍增)的更多相关文章

  1. Codeforces 1511G - Chips on a Board(01trie/倍增)

    Codeforces 题面传送门 & 洛谷题面传送门 一道名副其实的 hot tea 首先显然可以发现这俩人在玩 Nim 游戏,因此对于一个 \(c_i\in[l,r]\) 其 SG 值就是 ...

  2. Architecture of Device I/O Drivers, Device Driver Design

    http://www.kalinskyassociates.com/Wpaper4.html Architecture of Device I/O Drivers Many embedded syst ...

  3. ARM JTAG 信号 RTCK 应该如何处理?

    用户在调试内嵌可综合内核的 CPU 如 ARM7TDMI-S 时,需要通过打开仿真器的自适应时钟功能. 此时,ARM仿真器根据 RTCK 时钟信号的频率,产生可用于 CPU 内核当前时钟主频的最快的 ...

  4. Implementation of Serial Wire JTAG flash programming in ARM Cortex M3 Processors

    Implementation of Serial Wire JTAG flash programming in ARM Cortex M3 Processors The goal of the pro ...

  5. CF1511G-Chips on a Board【倍增】

    正题 题目链接:https://www.luogu.com.cn/problem/CF1511G 题目大意 给出\(n*m\)的棋盘上每一行有一个棋子,双方轮流操作可以把一个棋子向左移动若干步(不能不 ...

  6. Codeforces Round #194 (Div. 2) D. Chips

    D. Chips time limit per test:1 second memory limit per test:256 megabytes input:standard input outpu ...

  7. ACM-ICPC Beijing 2016 Genius ACM(倍增+二分)

    描述 给定一个整数 M,对于任意一个整数集合 S,定义“校验值”如下: 从集合 S 中取出 M 对数(即 2∗M 个数,不能重复使用集合中的数,如果 S 中的整 数不够 M 对,则取到不能取为止),使 ...

  8. CH0601 Genius ACM【倍增】【归并排序】

    0601 Genius ACM 0x00「基本算法」例题 描述 给定一个整数 M,对于任意一个整数集合 S,定义“校验值”如下: 从集合 S 中取出 M 对数(即 2∗M 个数,不能重复使用集合中的数 ...

  9. Codeforces Round #194 (Div. 1) B. Chips 水题

    B. Chips Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/333/problem/B D ...

随机推荐

  1. 『忘了再学』Shell基础 — 28、AWK中条件表达式说明

    目录 1.AWK的条件表达 2.条件表达式说明 (1)BEGIN (2)END (3)关系运算符 (4)说明AWK中条件表达式的执行过程 (5)AWK中使用正则表达式 (6)A~B练习 1.AWK的条 ...

  2. DS18B20数字温度计 (一) 电气特性, 供电和接线方式

    目录 DS18B20数字温度计 (一) 电气特性, 供电和接线方式 DS18B20数字温度计 (二) 测温, ROM和CRC校验 DS18B20数字温度计 (三) 1-WIRE总线ROM搜索算法 DS ...

  3. 【spring源码系列】之【FactoryBean类型的接口】

    1.概述 目前我们知道,spring创建bean有多种方式,比如xml方式创建,比如@Component,@Service,@Controler,@Repository注解创建,比如@Autowire ...

  4. 使用PowerShell安装MySQL

    更新记录 2022年4月16日:本文迁移自Panda666原博客,原发布时间:2021年7月10日. 2022年4月16日:更新MySQL下载链接. 一.说明与准备工作 根据MySQL官网提供的安装M ...

  5. 解决maven依赖冲突,这篇就够了!

    一.前言 什么是依赖冲突 依赖冲突是指项目依赖的某一个jar包,有多个不同的版本,因而造成了包版本冲突. 依赖冲突的原因 我们在maven项目的pom中 一般会引用许许多多的dependency.例如 ...

  6. 1.2 操作系统的第二个功能——并发功能 -《zobolの操作系统学习札记》

    1.2 操作系统的第二个功能--并发功能 目录 1.2 操作系统的第二个功能--并发功能 问1:什么是并发功能?并发功能是必要的吗? 问2:并发功能必须要求拥有多核CPU吗? 问3:多核CPU和单核C ...

  7. TCP和UDP协议的区别以及原理

    参考文章https://blog.csdn.net/weixin_38483133/article/details/123864253

  8. 如何编写测试团队通用的Jmeter脚本

    平时学习.工作过程中,编写的一些jmeter脚本,相信大多数都遇到过这个问题.那就是:如果换一台电脑运行,文件路径不一样,会导致运行失败. 前不久,自己就真真切切遇到过一回,A同学写了个脚本用于压测, ...

  9. 抢先体验! 在浏览器里写 Flutter 是一种什么体验?

    Invertase 是一间位于英国的开源软件制作公司.主要构建关于开发者工具.SDK 等应用程序,早在 Flutter 2.2 的时候,Invertase 团队就开始帮助构建和贡献 Firebase ...

  10. IDEA 开发工具-插件{[转载]

    00 idea 开发工具使用技巧 01 idea插件推荐-- 02 IDEA插件 03 IDEA值得推荐的20款优秀的插件 04 IDEA插件精选」安利一个IDEA骚操作:一键生成方法的序列图