CF339D Xenia and Bit Operations
题意:
有
2
n
2^n
2n个数,有
m
m
m个操作,每次修改一个数,然后你要输出
(
(
a
1
∣
a
2
)
x
o
r
(
a
3
∣
a
4
)
)
∣
(
(
a
5
∣
a
6
)
x
o
r
(
a
7
∣
a
8
)
)
.
.
.
.
( (a1|a2)xor(a3|a4) )|( (a5|a6)xor(a7|a8) )....
((a1∣a2)xor(a3∣a4))∣((a5∣a6)xor(a7∣a8))....
即
o
r
or
or
x
o
r
xor
xor 交替计算。
第一行两个数字
n
,
m
n,m
n,m。
第二行
2
n
2^n
2n 个数字。
下面
m
m
m行,每行两个数字
x
,
y
x,y
x,y,将第
x
x
x个数字改为
y
y
y。
保证
1
≤
n
≤
17
,
1
≤
m
≤
1
0
5
1\le n \le 17\ , \ 1\le m \le 10^5
1≤n≤17 , 1≤m≤105 ,数字任意时刻满足
0
≤
x
≤
2
30
0\le x \le 2^{30}
0≤x≤230
共
m
m
m行,输出每次改完数字后上述表达式的值。
思路:
考虑线段树解决,单点修改十分容易。 重点在于如何在
p
u
s
h
u
p
pushup
pushup中维护答案。 通过观察可以发现,
p
u
s
h
u
p
pushup
pushup中
左右区间合并时,长度为
2
2
2的奇数次幂的区间合并
p
u
s
h
u
p
pushup
pushup需要
∣
|
∣操作。左右区间合并时,长度为
2
2
2的偶数次幂的区间合并
p
u
s
h
u
p
pushup
pushup需要
x
o
r
xor
xor操作。
因此,
p
u
s
h
u
p
pushup
pushup中分类讨论即可解决问题。
Code:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<cstring>
#include<string>
#include<math.h>
#include<algorithm>
#include<bits/stdc++.h>
#include<map>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
#define cuttime ios::sync_with_stdio(false)
#define swap(x, y) x ^= y, y ^= x, x^= y
#define INF 0x3f3f3f3f
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dep(i,a,b) for(int i=(a);i>=(b);--i)
#define scan1(x) scanf("%d",&x)
#define scan2(x,y) scanf("%d%d",&x,&y)
#define scan3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define scanll1(x) scanf("%lld",&x)
#define scanll2(x,y) scanf("%lld%lld",&x,&y)
#define scanll3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
#define lowbit(x) (x&(-x))
#define mid ((l+r)>>1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define debug(x) cout <<#x<<": "<<x<<endl
using namespace std
;
typedef unsigned long long ull
;
typedef long long ll
;
const int N
=5e5+20;
const int MAX
=10000007;
inline ll
read() {
char c
=getchar();ll x
=0,f
=1;
while(c
<'0'||c
>'9'){if(c
=='-')f
=-1;c
=getchar();}
while(c
>='0'&&c
<='9'){x
=x
*10+c
-'0',c
=getchar();}
return x
*f
;
}
inline void out(ll x
) {
if(x
>9) out(x
/10);
putchar(x
%10+'0');
}
ll a
[N
];
ll sum
[N
];
ll tree
[N
];
ll
qsm(ll a
,ll b
){
ll ans
=1;
while(b
){
if(b
&1){
ans
=ans
*a
;
}
a
=a
*a
;
b
>>=1;
}
return ans
;
}
void pushup(int l
,int r
,int rt
){
int mi
;
rep(i
,1,32){
if(qsm(2,i
)==(r
-l
+1)){
mi
=i
;
break;
}
}
if(mi
%2){
tree
[rt
]=(tree
[rt
<<1]|tree
[rt
<<1|1]);
}
else{
tree
[rt
]=(tree
[rt
<<1]^tree
[rt
<<1|1]);
}
}
void build(int l
,int r
,int rt
){
if(l
==r
){
tree
[rt
]=a
[l
];
return ;
}
build(lson
);
build(rson
);
pushup(l
,r
,rt
);
}
void update(int L
,int R
,int l
,int r
,int rt
,int val
){
if(L
<=l
&&r
<=R
){
a
[l
]=val
;
tree
[rt
]=val
;
return ;
}
if(L
<=mid
)update(L
,R
,lson
,val
);
if(R
>mid
)update(L
,R
,rson
,val
);
pushup(l
,r
,rt
);
}
map
<ll
,ll
>mp
;
int n
,m
;
int main(){
int n
,m
;
scan2(n
,m
);
rep(i
,1,qsm(2,n
)){
a
[i
]=read();
}
build(1,qsm(2,n
),1);
rep(i
,1,m
){
int x
,y
;
scan2(x
,y
);
update(x
,x
,1,qsm(2,n
),1,y
);
out(tree
[1]);
puts("");
}
return 0;
}