记$V=2^{20}-1$,即值域范围,也可以作为"全集"

显然与$a_{i}$的顺序无关,对所有$a_{i}$维护一棵trie树

关于如何维护这棵trie树,考虑使用分裂+合并的方式,即:1.分裂出区间对应的trie树;2.操作分裂出的trie树;3.合并分裂出的tire树和原trie树

(关于时间复杂度后面会进行统一分析,暂时不需要考虑)

对于分裂(第1步),使用类似线段树查询的方法

对于合并(第3步),使用类似线段树合并的方法(即在其中一个子树为空时直接选择另一个子树)

对于操作(第2步),对不同的操作类型分类讨论——

查询操作:维护子树大小(子树内数值数量),直接输出即可

与操作:将其转化为异或$V$、或$x\oplus V$、异或$V$,那么只需要考虑异或和或操作即可

异或操作:直接在根节点上打懒标记,对于区间$[l,r]$的懒标记$tag$仅考虑$tag\and (r-l)$的结果,因此在下传标记时,若$tag\and \frac{r-l+1}{2}$非0则交换$[l,r]$的左右儿子

或操作:递归所有节点,当递归到区间$[l,r]$时,若$x\and \frac{r-l+1}{2}$非0则在$[l,r]$的左子树上打异或$\frac{r-l+1}{2}$的懒标记并合并$[l,r]$的左右子树(其中$x$为操作权值),再做如下剪枝——

维护子树与(子树内所有数值的与)和子树或,设当前子树两者分别为$v_{1}$和$v_{2}$,若$x\and (v_{1}\oplus v_{2}\oplus V)=x$(即子树内所有权值在$x$为1的位上都相同)则直接打上异或$x\and (v_{1}\oplus V)$的懒标记即可

("在$[l,r]$的左子树上打异或$\frac{r-l+1}{2}$的懒标记"的实际目的是维护子树与和子树或)

下面,来分析时间复杂度:

定义节点$x$的势能为$1+\log V+(v_{1}\oplus v_{2})$中1的个数(其中$v_{1}$和$v_{2}$为子树与和子树或,后者即$x$子树中仍未完全相同的位数),分别考虑这些操作的均摊复杂度——

分裂新建$o(\log V)$个节点,一个节点的势能为$o(\log V)$,即$o(\log^{2}V)$

合并递归过程中,若继续递归,即会合并两个节点,合并后势能减少$o(1)$,即均摊复杂度为$o(1)$

异或(打懒标记)不影响势能,即均摊复杂度为$o(1)$

或操作递归过程中,若不满足剪枝,必然会使得$v_{1}\oplus v_{2}$中1的个数减少1个,即均摊复杂度为$o(1)$

另外,势能和的范围显然也是​$o(n\log^{2}V)$

综上所述,总均摊复杂度为$o(n\log^{2}V)$,可以通过

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 8000005
4 #define V ((1<<20)-1)
5 #define mid (l+r>>1)
6 int V_trie,rt,n,m,p,x,y,z,ls[N],rs[N],sz[N],And[N],Or[N],tag[N];
7 int New(){
8 int k=++V_trie;
9 And[k]=V;
10 return k;
11 }
12 void upd_xor(int k,int l,int r,int x){
13 if (!k)return;
14 tag[k]^=x;
15 int p=((And[k]&(x^V))|((Or[k]^V)&x));
16 Or[k]=((Or[k]&(x^V))|((And[k]^V)&x));
17 And[k]=p;
18 }
19 void up(int k){
20 sz[k]=sz[ls[k]]+sz[rs[k]];
21 And[k]=(And[ls[k]]&And[rs[k]]);
22 Or[k]=(Or[ls[k]]|Or[rs[k]]);
23 }
24 void down(int k,int l,int r){
25 if (tag[k]&((r-l+1)>>1))swap(ls[k],rs[k]);
26 upd_xor(ls[k],l,mid,tag[k]);
27 upd_xor(rs[k],mid+1,r,tag[k]);
28 tag[k]=0;
29 }
30 void add(int &k,int l,int r,int x){
31 if (!k)k=New();
32 if (l==r){
33 sz[k]=1,And[k]=Or[k]=x;
34 return;
35 }
36 if (x<=mid)add(ls[k],l,mid,x);
37 else add(rs[k],mid+1,r,x);
38 up(k);
39 }
40 int split(int &k,int l,int r,int x,int y){
41 if ((!k)||(l>y)||(x>r))return 0;
42 if ((x<=l)&&(r<=y)){
43 int p=k;
44 k=0;
45 return p;
46 }
47 down(k,l,r);
48 int kk=New();
49 ls[kk]=split(ls[k],l,mid,x,y);
50 rs[kk]=split(rs[k],mid+1,r,x,y);
51 up(k),up(kk);
52 return kk;
53 }
54 void merge(int &k1,int k2,int l,int r){
55 if ((!k1)||(!k2)){
56 k1+=k2;
57 return;
58 }
59 if (l==r){
60 sz[k1]=max(sz[k1],sz[k2]);
61 And[k1]&=And[k2];
62 Or[k1]|=Or[k2];
63 return;
64 }
65 down(k1,l,r),down(k2,l,r);
66 merge(ls[k1],ls[k2],l,mid);
67 merge(rs[k1],rs[k2],mid+1,r);
68 up(k1);
69 }
70 void upd_or(int k,int l,int r,int x){
71 if (!k)return;
72 if ((x&(And[k]^Or[k]^V))==x){
73 upd_xor(k,l,r,(x&(And[k]^V)));
74 return;
75 }
76 down(k,l,r);
77 if (x&((r-l+1)>>1)){
78 upd_xor(ls[k],l,mid,((r-l+1)>>1));
79 merge(rs[k],ls[k],mid+1,r);
80 ls[k]=0;
81 }
82 upd_or(ls[k],l,mid,x);
83 upd_or(rs[k],mid+1,r,x);
84 up(k);
85 }
86 int main(){
87 scanf("%d%d",&n,&m);
88 And[0]=V;
89 for(int i=1;i<=n;i++){
90 scanf("%d",&x);
91 add(rt,0,V,x);
92 }
93 for(int i=1;i<=m;i++){
94 scanf("%d%d%d",&p,&x,&y);
95 int k=split(rt,0,V,x,y);
96 if (p==4)printf("%d\n",sz[k]);
97 else{
98 scanf("%d",&z);
99 if (p==1){
100 upd_xor(k,0,V,V);
101 upd_or(k,0,V,(z^V));
102 upd_xor(k,0,V,V);
103 }
104 if (p==2)upd_or(k,0,V,z);
105 if (p==3)upd_xor(k,0,V,z);
106 }
107 merge(rt,k,0,V);
108 }
109 }

[cf1515H]Phoenix and Bits的更多相关文章

  1. Phoenix综述(史上最全Phoenix中文文档)

    个人主页:http://www.linbingdong.com 简书地址:http://www.jianshu.com/users/6cb45a00b49c/latest_articles 网上关于P ...

  2. 在DBeaver中phoenix查询报错:org.apache.phoenix.exception.PhoenixIOException: The system cannot find the path specified

    环境:Phoenix:4.4,win7系统 问题:Phoenix在查询hbase时,报"系统找不到指定路径". 解决: 请参见 https://distcp.quora.com/C ...

  3. [LeetCode] Number of 1 Bits 位1的个数

    Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also know ...

  4. [LeetCode] Reverse Bits 翻转位

    Reverse bits of a given 32 bits unsigned integer. For example, given input 43261596 (represented in ...

  5. HBase+Phoenix整合入门--集群搭建

    环境:CentOS 6.6 64位    hbase 1.1.15  phoenix-4.7.0-HBase-1.1 一.前置环境: 已经安装配置好Hadoop 2.6和jdk 1.7 二.安装hba ...

  6. 【leetcode】Number of 1 Bits

    题目描述: Write a function that takes an unsigned integer and returns the number of '1' bits it has (als ...

  7. SQL Server恢复软件 Stellar Phoenix sql recovery

    SQL Server恢复软件 Stellar Phoenix sql recovery http://www.stellarinfo.com/ http://www.stellarinfo.com/ ...

  8. Leetcode-190 Reverse Bits

    #190. Reverse Bits Reverse bits of a given 32 bits unsigned integer. For example, given input 432615 ...

  9. CodeForces 485C Bits[贪心 二进制]

    C. Bits time limit per test1 second memory limit per test256 megabytes inputstandard input outputsta ...

随机推荐

  1. 基于Jetpack组件构建的开源项目-WanLearning

    「WanLearning App」基于 Material Design 风格构建的 玩 Android 客户端,主要是为了适应Kotlin语言开发流程. 主要特点 基于Google官方宣贯的MVVM模 ...

  2. 实践篇 -- Redis客户端缓存在SpringBoot应用的探究

    本文探究Redis最新特性--客户端缓存在SpringBoot上的应用实战. Redis Tracking Redis客户端缓存机制基于Redis Tracking机制实现的.我们先了解一下Redis ...

  3. SAE助力南瓜电影7天内全面Severless

    作者:李刚(寻如),阿里云解决方案架构师 南瓜电影APP是国内领先的专注于影视精品化运营的垂直类视频产品,在移动互联网.IPTV.OTT等客户端,面向广大中产阶级精英群体,提供有异于院线及其他视频平台 ...

  4. 用C++实现的数独解题程序 SudokuSolver 2.3 及实例分析

    SudokuSolver 2.3 程序实现 用C++实现的数独解题程序 SudokuSolver 2.2 及实例分析 里新发现了一处可以改进 grp 算法的地方,本次版本实现了对应的改进 grp 算法 ...

  5. 力扣 - 剑指 Offer 17. 打印从1到最大的n位数

    题目 剑指 Offer 17. 打印从1到最大的n位数 思路1 如果有n位,那么最大值就是\(10^n-1\),即如果n是2,那么最大就到输出到99 考虑到大数情况,所以使用字符数组 还要把字符数组转 ...

  6. 初探JavaScript PDF blob转换为Word docx方法

    PDF转WORD为什么是历史难题 PDF 转Word 是一个非常非常普遍的需求,可谓人人忌危,为什么如此普遍的需求,却如此难行呢,还得看为什么会有这样的一个需求: PDF文档遵循iOS32000的规范 ...

  7. Coursera Deep Learning笔记 结构化机器学习项目 (上)

    参考:https://blog.csdn.net/red_stone1/article/details/78519599 1. 正交化(Orthogonalization) 机器学习中有许多参数.超参 ...

  8. 2021.9.7考试总结[NOIP模拟49]

    T1 Reverse $BFS$暴力$O(n^2)$ 过程中重复枚举了很多点,考虑用链表记录当前点后面可到达的第一个未更新点. 搜索时枚举翻转子串的左端点,之后便可以算出翻转后$1$的位置. $cod ...

  9. 难搞的C语言指针你搞懂了多少

    C语言指针说难不难但是说容易又是最容易出错的地方,因此不管是你要做什么只要用到C指针你就跳不过,今天咱们就以 十九个例子来给大家简单的分析一下指针的应用,最后会有C语言视频资料提供给大家更加深入的参考 ...

  10. 六步教你如何用PADS进行PCB设计?

    在使用PADS进行PCB设计的过程中,需要对印制板的设计流程以及相关的注意事项进行重点关注,这样才能更好的为工作组中的设计人员提供系统的设计规范,同时也方便设计人员之间进行相互的交流和检查. 02 设 ...