题目背景
可怜的 dead_X 收不了歌,于是他出了个水题并给参赛者送了 100100 分。
2022 Update: 已经收了,很水。
题目描述
你需要维护一个序列。
这个序列开始时有 2𝑛2n 个数,下标从 00 开始。第 𝑖i 个数初始值为 𝑖i,需要支持以下三种操作:
- 定义 𝑎a 为所有下标为偶数的数组成的子序列,𝑏b 为所有下标为奇数的数组成的子序列,将 𝑎,𝑏a,b 连接,构成新的序列。
- 定义 𝑎a 为所有下标为奇数的数组成的子序列,𝑏b 为所有下标为偶数的数组成的子序列,将 𝑎,𝑏a,b 连接,构成新的序列。
- 查询下标为 𝑥x 的数。
总共将进行 𝑚m 次操作。
输入格式
第一行输入两个正整数 𝑛,𝑚n,m。
接下来输入 𝑚m 行,每行输入两个非负整数 𝑜𝑝,𝑥op,x,代表一次操作。
如果 𝑜𝑝=1op=1,若 𝑥=0x=0,代表第一种操作,若 𝑥=1x=1,代表第二种操作。
如果 𝑜𝑝=2op=2,代表第三种操作,参数 𝑥x 即为输入的 𝑥x。
输出格式
对于每个 𝑜𝑝=2op=2 输出一行,即对应的数。
输入输出样例
输入 #1
2 7 2 0 1 0 2 1 1 1 2 2 1 0 2 3
输出 #1
0 2 0 1
说明/提示
【样例解释】
所有操作前后的序列从左至右的数如下:
{0,1,2,3}{0,1,2,3}
下标为 00 的数为 00。
{0,2},{1,3}{0,2},{1,3}
{0,2,1,3}{0,2,1,3}
下标为 11 的数为 22。
{2,3},{0,1}{2,3},{0,1}
{2,3,0,1}{2,3,0,1}
下标为 22 的数为 00。
{2,0},{3,1}{2,0},{3,1}
{2,0,3,1}{2,0,3,1}
下标为 33 的数为 11。
【数据范围】
本题采用捆绑测试。
- Subtask 1(10 points):不存在 𝑜𝑝=1op=1 的操作。
- Subtask 2(10 points):𝑛≤10,𝑚≤103n≤10,m≤103。
- Subtask 3(20 points):𝑛≤10n≤10。
- Subtask 4(20 points):𝑚≤103m≤103。
- Subtask 5(20 points):对于 𝑜𝑝=1op=1 的操作,𝑥=0x=0。
- Subtask 6(20 points):无特殊限制。
对于 100%100% 的数据,1≤𝑛≤321≤n≤32,1≤𝑚≤1061≤m≤106。
若 𝑜𝑝=1op=1,𝑥∈{0,1}x∈{0,1},若 𝑜𝑝=2op=2,0≤𝑥<2𝑛0≤x<2n。
Code:
#include<bits/stdc++.h>
using namespace std;
#define int unsigned int
int cnt,op,x,n,m,y;
inline void read(int &res){
res=0;
int f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){res=(res<<1)+(res<<3)+c-48;c=getchar();}
res*=f;
}
inline void write(int x){
if(x==0){
putchar('0');
return;
}
char f[205];
int tmp=x>0?x:-x;
if(x<0)putchar('-');
int cnt=0;
while(tmp>0){
f[cnt++]=tmp%10+'0';
tmp/=10;
}
while(cnt>0)putchar(f[--cnt]);
}
signed main()
{
read(n);read(m);
while(m--){
read(op);read(x);
if(op==1){
if(x==1){
y^=1<<cnt;
}
cnt++;
if(cnt>=n)cnt=0;
continue;
}
write(((x>>(n-cnt))|((x&((1<<(n-cnt))-1))<<cnt))^y);
putchar(10);
}
return 0;
}