膜拜azui
题目
膜拜 azui
(azui.cpp/c/pas)
【问题描述】
一天,小 A 给了 J·G 一道水题,J·G 一眼秒了,现在 J·G 想考
考你们:
小 A 有 N 个灯,排成了一列,现在小 A 给出来一个叫做 azui 的奇葩操作,我们把开着的灯看作数字 1,把关着的灯看作数字 0,定义
0 azui 0 = 1,0 azui 1 = 0,1 azui 1 = 1, 1 azui 0 = 0。现在小 A 有 N 个问题
azui(l,r),表示询问从左往右的第 l 个灯向右一个一个 azui 到第 r 个灯
的结果是什么。
【输入】
第1 行一个整数 N 表示序列的长度。
第2 行 N 个整数 Ai,每个数不是 0 就是 1,表示灯是关的还是开
的。
第3 行一个整数 M 表示询问的个数。
第4~M+3 行,每行两个整数 l 和 r,表示询问 azui(l,r)。
【输出】
共 M 行,第 i 行回答第 i 个询问。
【样例输入】
5
1 0 1 0 1
5
分析
讲讲我的心路历程。
首先这个a azui b
运算就是return a==b
,它有一个专业术语,叫做同或。
在考试的时候,我前半个小时完全没有思路,写一个暴力程序然后看着她它发呆。兰后我掏出了一个草稿本,手动全排列来计算azui值。
如下:
000 0
001 1
010 1
100 1
011 0
101 0
110 0
111 1
以此类推,把4枚举到一半,发现,哇,好有规律呀!!
我发现了规律1:同或有结合律。也就是说,给定数量的0和1,最后的结果总是固定的,与顺序无关。
这个也很好证明,分类讨论就行了。
于是我写了个程序打表:
括号里左边是0的数量,右边是1的数量。
横着看,000000000,11111111,000000000,1111111111,0000000……
博主又在中八了
我们可以发现规律2:同或的结果取决于0的数量,值可能大概应该也许就一定是零的个数模2取反。
然后就简单了,用个前缀和来保存零的个数,然后直接
Θ(1)
的时间复杂度求。
代码
#include<cstdio>
void Read(int &p)
{
p=0;
int f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
p=p*10+c-'0',c=getchar();
p*=f;
}
int N,M,sig0[1002017],a[1002017],l,r;
int main()
{
freopen("azui.in","r",stdin);
freopen("azui.out","w",stdout);
sig0[0]=0;
Read(N);
for(int i=1;i<=N;i++)
Read(a[i]),sig0[i]=sig0[i-1]+(a[i]^1);
Read(M);
for(int i=1;i<=M;i++)
{
Read(l),Read(r);
if(l==r) printf("%d\n",a[l]);
else printf("%d\n",!((sig0[r]-sig0[l-1])%2));
}
return 0;
}