压 位 T r i e 入 门 练 习 题(确信)

题意很清楚(

让我们先来想一想,如果没有排序操作的话,这道题应该怎么做。

我们维护一个 \(x\) 表示从开始到现在一共异或上了 \(x\),在序列末尾插入一个 \(n\) 相当于插入 \(n \bigoplus x\)。

现在的问题就是:

  1. 询问 \(\sum_{i=l}^ra_i \bigoplus x\)
  2. 改变 \(x\)。

位运算相关的还是考虑按位拆分比较好。

如果我们能够知道这个区间中的第 \(k\) 位有多少个 \(1\),似乎就能够 \(O(k)\) 计算这一位对答案的贡献了。

于是我们使用一颗线段树来维护这个序列,每个位置开一个 \(\log V\) 的数组来维护这个东西,插入和询问的复杂度均为 \(O(\log n\log V)\)。

那么我们加上排序操作?

众所周知 01trie 就是线段树,于是我们先把线段树改成 01trie。

我们发现异或上一个数可以看做将某几层的左儿子和右儿子交换。

然后在询问的时候搞清楚这一层有没有交换左右儿子,然后判断究竟该走哪边和该加上哪边就行了。

至于实现的话,对排序后的部分开一颗 01trie,未排序的部分直接使用前缀和统计。

时空复杂度都是 \(O((n+m)\log^2V)\)。

然而你发现这样算下来大概是 660MB,会被卡空间。。。

如果我们能够将 01trie 的节点数量减少,那么我们就可以把空间压下来了。

所以我们将 01trie 改成压两位的 压位 trie(也就是每个节点的度数为 \(4\)),空间就可以除以 \(2\) 了。

因为儿子个数并不是瓶颈,可以通过。

虽然说吧,你可以去赌 lxl 的插入操作很少,但是这明显还是会被卡(

以及细节巨多,需要判相同的数,还要判断我在什么时候异或上了多少。

#include<cstdio>
typedef unsigned ui;
const ui M=1e5+5,N=M*32;
ui n,m,cnt,k,tk,l1,l2,rt,ans[31],a[M<<1],S[M<<1][31];ui L,X[2];
struct Node{
ui sz,chi[4],ans[31];
inline ui&operator[](const ui&x){
return chi[x];
}
}t[N];
inline void swap(ui&a,ui&b){
ui c=a;a=b;b=c;
}
ui Find(const ui&u,ui x,const ui&id=14){
if(!u)return X[L++]=x,0;if(!~id)return X[L++]=x,0;const ui&k=tk>>(id<<1)&3;
if(x<=t[t[u][0^k]].sz)return Find(t[u][0^k],x,id-1)|0<<(id<<1);x-=t[t[u][0^k]].sz;
if(x<=t[t[u][1^k]].sz)return Find(t[u][1^k],x,id-1)|1<<(id<<1);x-=t[t[u][1^k]].sz;
if(x<=t[t[u][2^k]].sz)return Find(t[u][2^k],x,id-1)|2<<(id<<1);x-=t[t[u][2^k]].sz;
if(x<=t[t[u][3^k]].sz)return Find(t[u][3^k],x,id-1)|3<<(id<<1);x-=t[t[u][3^k]].sz;
}
void Qry(const ui&u,const ui&l,const ui&r,const ui&L=0,const ui&R=(1<<30)-1,const ui&id=14){
if(!u||l>R||L>r)return;
if(l<=L&&R<=r){
for(ui i=0;i<=30;++i)ans[i]+=t[u].ans[i];return;
}
ui k=tk>>(id<<1)&3,m1,m2,m3;m2=L+R>>1;m1=L+m2>>1;m3=m2+1+R>>1;
Qry(t[u][0^k],l,r,L,m1,id-1);Qry(t[u][1^k],l,r,m1+1,m2,id-1);
Qry(t[u][2^k],l,r,m2+1,m3,id-1);Qry(t[u][3^k],l,r,m3+1,R,id-1);
}
void Insert(const ui&x){
ui u=rt,id=14;
while(~id){
++t[u].sz;for(ui i=0;i<=30;++i)if(x>>i&1)++t[u].ans[i];
if(!t[u][x>>(id<<1)&3])t[u][x>>(id<<1)&3]=++cnt;u=t[u][x>>(id<<1)&3];--id;
}
++t[u].sz;for(ui i=0;i<=30;++i)if(x>>i&1)++t[u].ans[i];
}
inline void ins(const ui&x,const ui&id){
for(ui i=0;i<=30;++i)S[id][i]=S[id-1][i]+(x>>i&1);a[id]=x;
}
signed main(){
ui i,x,l,r,q,p,opt;unsigned long long sum;scanf("%u",&n);rt=++cnt;
for(i=1;i<=n;++i)scanf("%u",&x),ins(x,++l2);
scanf("%u",&m);
while(m--){
scanf("%u",&opt);
if(opt==1){
scanf("%u",&x);ins(x^k,++l2);
}
if(opt==2){
scanf("%u%u",&l,&r);for(i=0;i<=30;++i)ans[i]=0;sum=0;
if(r<=l1){
q=Find(rt,l);p=Find(rt,r);Qry(rt,q,p-1);--X[0];
for(i=0;i<=30;++i)sum+=1ull*(k>>i&1?r-l+1+X[0]-X[1]-ans[i]:ans[i])<<i;
sum+=1ull*(p^k^tk)*X[1];sum-=1ull*(q^k^tk)*X[0];
}
if(l<=l1&&l1<r){
q=Find(rt,l);Qry(rt,q,(1<<30)-1);--X[0];
for(i=0;i<=30;++i)sum+=1ull*(k>>i&1?l1-l+1+X[0]-ans[i]:ans[i])<<i;
for(i=0;i<=30;++i)sum+=1ull*(k>>i&1?r-l1-S[r-l1][i]:S[r-l1][i])<<i;
sum-=1ull*(q^k^tk)*X[0];
}
if(l1<l){
r-=l1;l-=l1;
for(i=0;i<=30;++i)sum+=1ull*(k>>i&1?r-l+1-(S[r][i]-S[l-1][i]):(S[r][i]-S[l-1][i]))<<i;
}
printf("%llu\n",sum);::L=0;
}
if(opt==3){
scanf("%u",&x);k^=x;
}
if(opt==4){
for(i=1;i<=l2;++i)Insert(a[i]);l1+=l2;tk=k;l2=0;
}
}
}

LGP5312题解的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. JDK版本基础知识解释

    感谢大佬:https://www.cnblogs.com/bjguanmu/articles/8710209.html jdk:java development kit,是程序员编写java程序需要的 ...

  2. 虚拟机与Docker

    https://www.cnblogs.com/kex1n/p/6933039.html https://blog.csdn.net/jingzhunbiancheng/article/details ...

  3. LaunchScreen原理

    会自动加载LaunchScreen是因为在Target当中,指定了Launch Screen file 它的底层实现其实把LaunchScreen上的东西,生成了一张图片,然后把这张图片设为程序的启动 ...

  4. 在view中实现UIViewController的跳转 By H.L

    view中是不能进行UIViewController的push,pop等操作的,若进行跳转操作,一般是用代理,block,通知等实现,那如何实现在ViewController的subView中实现跳转 ...

  5. mapTest

    import java.util.*;public class mapTest { public static void main(String[] args) throws Exception{ L ...

  6. Ansible 自动化运维管理工具

    Ansible 自动化运维管理工具 1.Ansible概述 2.Ansible部署 3.Ansible模块 1.Ansible概述: Ansible是一个基于Python开发的配置管理和应用部署工具, ...

  7. 类(静态)变量和类(静态)static方法以及main方法、代码块,final方法的使用,单例设计模式

    类的加载:时间 1.创建对象实例(new 一个新对象时) 2.创建子类对象实例,父类也会被加载 3.使用类的静态成员时(静态属性,静态方法) 一.static 静态变量:类变量,静态属性(会被该类的所 ...

  8. socket 套接字编程

    今日内容 socket 套接字编程 简易服务端与客户端代码实现 通信循环 黏包现象(TCP协议) 报头制作.struct 模块.封装形式 内容详细 一.socket 套接字编程 实现一款能够进行数据交 ...

  9. 『无为则无心』Python面向对象 — 46、类和对象

    目录 1.理解类和对象 2.类 3.对象 4.Python中的对象 5.类和对象的定义 (1)定义类 (2)创建对象 (3)练习 6.拓展:isinstance() 函数 1.理解类和对象 (1)类和 ...

  10. 多表查询思路、navicat可视化软件、python操作MySQL、SQL注入问题以及其他补充知识

    昨日内容回顾 外键字段 # 就是用来建立表与表之间的关系的字段 表关系判断 # 一对一 # 一对多 # 多对多 """通过换位思考判断""" ...