题面:
题意:
给定一棵树,点有点权。
有以下三种操作:
(1)将 1 − − x 1--x 1−−x上面的所有的点的点权都 按位或上一个数 t t t。
(2)将 1 − − x 1--x 1−−x上面的所有的点的点权都 按位与上一个数 t t t。
(3)询问 1 − − x 1--x 1−−x上面所有数的异或和。
题解:
对于 1 − − x 1--x 1−−x的处理可以使用树剖处理。
对于每一位建立一棵线段树,总共是31棵线段树。线段树上维护区间中这一位为 1 的数的个数。
这样对数的处理就转化为了对每一位的单独处理。
对于某一位来说,
对于操作1,如果 t t t 的这一位为 0,那么相当于 1 − − x 1--x 1−−x 节点这一位的权值未变。如果 t t t 的这一位为 1,相当于 1 − − x 1--x 1−−x 节点的这一位的权值都变为 1。
对于操作2,如果 t t t 的这一位为 0,那么相当于 1 − − x 1--x 1−−x 节点这一位的权值都变为0。如果 t t t 的这一位为 1,相当于 1 − − x 1--x 1−−x 节点的这一位的权值未变。
对于操作3,只需要统计 1 − − x 1--x 1−−x 每一位的1的个数是奇数个还是偶数个即可。
时间复杂度 O ( 31 ∗ n ∗ l o g 2 n ) O(31*n*log^2n) O(31∗n∗log2n),有点大。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<vector>
#define ll long long
#define llu unsigned ll
using namespace std;
char buffer[100001],*S,*T;
inline char Get_Char()
{
if (S==T)
{
T=(S=buffer)+fread