CF339D Xenia and Bit Operations

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) ).... ((a1a2)xor(a3a4))((a5a6)xor(a7a8))....

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 1n17 , 1m105 ,数字任意时刻满足 0 ≤ x ≤ 2 30 0\le x \le 2^{30} 0x230

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];
/**
 * 线段树
 * @param  a [description]
 * @param  b [description]
 * @return   [description]
 */
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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值