线段树+思维 Codeforces Round #197 (Div. 2) D题 Xenia and Bit Operations

Xenia and Bit Operations

Xenia the beginner programmer has a sequence a, consisting of 2n non-negative integers: a1, a2, …, a2n. Xenia is currently studying bit operations. To better understand how they work, Xenia decided to calculate some value v for a.

Namely, it takes several iterations to calculate value v. At the first iteration, Xenia writes a new sequence a1 or a2, a3 or a4, …, a2n - 1 or a2n, consisting of 2n - 1 elements. In other words, she writes down the bit-wise OR of adjacent elements of sequence a. At the second iteration, Xenia writes the bitwise exclusive OR of adjacent elements of the sequence obtained after the first iteration. At the third iteration Xenia writes the bitwise OR of the adjacent elements of the sequence obtained after the second iteration. And so on; the operations of bitwise exclusive OR and bitwise OR alternate. In the end, she obtains a sequence consisting of one element, and that element is v.

Let’s consider an example. Suppose that sequence a = (1, 2, 3, 4). Then let’s write down all the transformations (1, 2, 3, 4)  →  (1 or 2 = 3, 3 or 4 = 7)  →  (3 xor 7 = 4). The result is v = 4.

You are given Xenia’s initial sequence. But to calculate value v for a given sequence would be too easy, so you are given additional m queries. Each query is a pair of integers p, b. Query p, b means that you need to perform the assignment ap = b. After each query, you need to print the new value v for the new sequence a.


题目大意:给你一个正整数序列,第一次操作:相邻的元素 | 运算,第二次操作:第一次操作完后得到的元素,相邻的元素 ^ 元素,循环这两种操作,直到序列只剩下一个元素;

怎么把这个问题转化到树上是最关键,可以发现,每次合并相邻的元素,不相邻的元素互不干扰,跟哈夫曼最优二叉树有点类似,知道了这个,就可以转化为线段树求解,单点修改,还要注意每次是 | 还是 ^ ,标记一下即可;

代码;

#include
#define LL long long
#define pa pair
#define ls k<<1
#define rs k<<1|1
#define inf 0x3f3f3f3f
using namespace std;
const int N=200100;
const int M=2000100;
const LL mod=1e9+7;
int n,m,a[N],opt[N];
struct Node{
	int l,r,w;
}tr[N*4];
void pp(int k){
	if(opt[ls]==1) tr[k].w=tr[ls].w|tr[rs].w;
	else if(opt[ls]==2) tr[k].w=tr[ls].w^tr[rs].w;
	opt[k]=3-opt[ls];
}
void build(int l,int r,int k){
	tr[k].l=l,tr[k].r=r;
	if(l==r){
		tr[k].w=a[l],opt[k]=1;
		return;
	}
	int d=(l+r)>>1;
	build(l,d,ls);
	build(d+1,r,rs);
	pp(k); 
}
void update(int pos,int w,int k){
	if(tr[k].l==tr[k].r){
		tr[k].w=w;
		return;
	}
	int d=(tr[k].l+tr[k].r)>>1;
	if(pos<=d) update(pos,w,ls);
	else update(pos,w,rs);
	pp(k);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=(1<<n);i++) scanf("%d",&a[i]);
	build(1,(1<<n),1);
	for(int i=1;i<=m;i++){
		int p,b;scanf("%d%d",&p,&b);
		update(p,b,1);
		printf("%d\n",tr[1].w);
	}
	return 0;
}

你可能感兴趣的:(#,(权值)线段树)