loj517 计算几何瞎暴力(Trie树)
题目:
分析:
操作4比较特殊,我们先来分析下操作4
操作4相当于需要一个数据结构,使得里面的数据有序(这有很多选择)
结合操作1,操作4的“排序”实际上指的是,将上一次排序之后加入的一些点,插入到这个数据结构中,ok,这也很中规中矩
于是我们需要一个数据结构和一个数组,数据结构存着有序的情况,数组存着后来插入的数,如果遇到了一个操作4,那么就把数组里的数一个一个插入到数据结构中
对于操作2,求区间和,也很中规中矩,很多有序的数据结构都可以支持区间和查询,对于另一部分的数组,也可以支持区间和查询
然后再看操作3,整体异或
我们先来考虑后面的数组如何整体异或:首先为了查询区间和,数组肯定要求前缀和,那么我们如何根据整体异或的修改来改变前缀和呢?其实很简单,我们不要单纯的前缀和,我们记下每一个二进制位(0,1)的前缀和,那么根据当前的整体异或值xortag的各个位的0/1情况,我们就知道贡献是多少。
然后考虑“数据结构”,很自然根据异或就想到Trie树,我们来看看Trie树如何满足所有的操作
操作1:不关Trie树的事
操作2:求区间和->求前缀和,注意到一个性质,那就是本题Trie树所管辖的下标区间,数字都是有序的,所以这里相当于求Trie树中最小的x个数的和;只需要记录每个点下面数字的个数size就行了;
操作3:对于一个整体标记tag,我们可以直接代数运算,这里主要提一下对于当前一个存在的tag,我们如何进行操作2的询问。我们将tag的每一位分解在Trie树上走,如果某一位tag为1,那么其实相当于左儿子'0'比右儿子'1'大,只需要颠倒判断一下即可
操作4:将数组中的元素一个一个插入到Trie树种即可
时间复杂度O((n+m)logn*logA)
细节:
1、注意,对于一个操作3,我们实际上并不能直接修改Trie树的tag值,因为修改了tag值其实表示我们的Trie树在当前tag值下有序,而一次操作3,但没有经过操作4,我们的Trie树对应的位置是不一定有序的,那么怎么处理呢?可以分开保存两个标记,一个tag表示当前Trie树在异或tag意义下有序(即上个操作4后的结果),一个xortag表示当前真正的异或值,在Trie树中,我们查询的时候就根据tag来,get子树和的时候就根据xortag来;然后外面的数组就一直是xortag,遇到操作4就把xortag传给Trie树的tag
2、在Trie树中查找前x小的数字的和的时候,要注意这种情况:比如最小数字0出现了3次,我现在想求最小的前2个数字和,那么这个时候就需要特判
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5,maxh=;
int xortag,n,m;
struct trie
{
int ch[maxn*maxh][];
int sz[maxn*maxh];
int sum[maxn*maxh][maxh];
int root=;
int len=;
int tag=;
void insert(int x)
{
int u=root;
for(int i=maxh-;i>=;--i)
{
int id=((x&(<<i))>);
if(!ch[u][id]) ch[u][id]=++len;
u=ch[u][id];
++sz[u];
for(int j=;j<maxh;++j)
if(x&(<<j)) sum[u][j]++;
}
}
long long getsum(int x)
{
long long ans=;
for(int i=;i<maxh;++i)
if(xortag&(<<i)) ans+=(sz[x]-sum[x][i])*(1LL<<i);else ans+=sum[x][i]*(1LL<<i);
return ans;
}
long long query(int x)
{
if(x==) return ;
int u=root;
long long ans=;
for(int i=maxh-;i>=;--i)
{
int l=,r=;
if(tag&(<<i)) swap(l,r);
if(x<=sz[ch[u][l]]) u=ch[u][l];
else
{
ans+=getsum(ch[u][l]);
x-=sz[ch[u][l]];
u=ch[u][r];
}
}
ans+=getsum(u)/sz[u]*x;
return ans;
}
int getsize()
{
return sz[ch[root][]]+sz[ch[root][]];
}
}Trie;
struct array
{
int a[maxn+];
int sum[maxn+][maxh];
int len=;
void insert(int x)
{
x^=xortag;
a[++len]=x;
for(int i=;i<maxh;++i)
sum[len][i]=sum[len-][i]+((x&(<<i))>);
}
long long query(int x)
{
long long ans=;
for(int i=;i<maxh;++i)
if(xortag&(<<i)) ans+=(x-sum[x][i])*(1LL<<i);else ans+=sum[x][i]*(1LL<<i);
return ans;
}
void transfer()
{
Trie.tag=xortag;
for(int i=;i<=len;++i)
Trie.insert(a[i]);
len=;
}
}Array;
long long query(int x)
{
if(x<=Trie.getsize()) return Trie.query(x);
else return Trie.query(Trie.getsize())+
Array.query(x-Trie.getsize());
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;++i)
{
int x;
scanf("%d",&x);
Array.insert(x);
}
scanf("%d",&m);
for(int i=;i<=m;++i)
{
int op,x,y;
scanf("%d",&op);
if(op==)
{
scanf("%d",&x);
Array.insert(x);
}
if(op==)
{
scanf("%d%d",&x,&y);
printf("%lld\n",query(y)-query(x-));
}
if(op==)
{
scanf("%d",&x);
xortag^=x;
}
if(op==) Array.transfer();
}
return ;
}
loj517 计算几何瞎暴力(Trie树)的更多相关文章
- loj517 计算几何瞎暴力
在序列上维护4个操作 1.在序列的尾端添加x 2.输出Al~Ar的和 3.将所有数异或x 4.将序列从小到大排序 第一眼看上去是Splay于是头铁硬刚了一发 后来发现splay没法异或 去百度“维护异 ...
- [LOJ#517]. 「LibreOJ β Round #2」计算几何瞎暴力[trie]
题意 题目链接 分析 记操作异或和为 \(tx\) ,最后一次排序时的异或和为 \(ax\) ,每个数插入时的 \(tx\) 记为 \(b\). 我们发现,一旦数列排序,就会变得容易操作. 对于新加入 ...
- LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力
二次联通门 : LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力 /* LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力 叫做计算几 ...
- 汕头市队赛 SRM14 T1 计算几何瞎暴力
计算几何瞎暴力 (easy.pas/c/cpp) 128MB 1s 在平面上,给定起点和终点,有一面墙(看作线段)不能穿过,问从起点走到终点的最短路程. 输入格式 输入一行,包含8个用空格分隔的整数x ...
- 「LibreOJ β Round #2」计算几何瞎暴力
https://loj.ac/problem/517 题解 首先我们如果没有排序这个骚操作的话,可以直接记一下各个数位的前缀和,然后异或标记给全局打,查询的时候先把区间信息提取出来然后整体异或就好了. ...
- 玲珑杯 round18 A 计算几何瞎暴力
题目链接 : http://www.ifrog.cc/acm/problem/1143 当时没看到坐标的数据范围= =看到讨论才意识到,不同的坐标最多只有1k多个,完全可以暴力做法,不过也要一些技巧. ...
- 玲珑杯”ACM比赛 Round #18 A -- 计算几何你瞎暴力(瞎暴力)
题目链接:http://www.ifrog.cc/acm/problem/1143?contest=1020&no=0 题解:就是瞎暴力具体多暴力看一下代码就知道了. #include < ...
- 洛谷P2412 查单词 [trie树 RMQ]
题目背景 滚粗了的HansBug在收拾旧英语书,然而他发现了什么奇妙的东西. 题目描述 udp2.T3如果遇到相同的字符串,输出后面的 蒟蒻HansBug在一本英语书里面找到了一个单词表,包含N个单词 ...
- 字符串 --- KMP Eentend-Kmp 自动机 trie图 trie树 后缀树 后缀数组
涉及到字符串的问题,无外乎这样一些算法和数据结构:自动机 KMP算法 Extend-KMP 后缀树 后缀数组 trie树 trie图及其应用.当然这些都是比较高级的数据结构和算法,而这里面最常用和最熟 ...
随机推荐
- SQLServer · 最佳实践 · SQL Server 2012 使用OFFSET分页遇到的问题
1. 背景 最近有一个客户遇到一个奇怪的问题,以前使用ROW_NUMBER来分页结果是正确的,但是替换为SQL SERVER 2012的OFFSET...FETCH NEXT来分页出现了问题,因此,这 ...
- android 解密工具
androguard. 这个是python写的 安装: pip install androguard
- String s = “1a2a3a4a” 解码为 “1234”
将字符串 String s = “1a2a3a4a” 解码为 “1234” public class Program2 { public static void main(String[] args ...
- ibatis 实现 物理级别的 分页 兼容多种数据库(转载)
最近在看iBatis时,想做用动态Sql做个分布.因为在做项目时用iBator工具生成没有分页的功能,只有一些我们常用的功能.所以要对生成后的代码做修改.我在Java高手真经的一书中看到有做了MySq ...
- NTP服务和DNS服务
1.NTP时间服务器 作用:NTP主要用于对计算机的时间同步管理操作 1.1 NTP部署 服务端:192.168.16.6 客户端:192.168.16.7 [root@localhost ~]# ...
- ps---图层,移动工具
1.移动图层从一个文件到另一个文件相当于复制,如果俩文件大小相同,开始移动后,按下shift键,可保持原来位置.若不相同,拖拽后,按shift,则会自动居中.如果目标文档包含选区,会到选区的中央. 2 ...
- python_正则_re模块
正则表达式元字符: 字符匹配 : . :除换行符以外的任意单个字符 [] :指定范围内字符 [^] :指定范围外字符 次数匹配: * :任意次,0,1,多次 .* :任意字符 任意次 ? :至多1次或 ...
- POJ 2631 Roads in the North (树的直径)
题意: 给定一棵树, 求树的直径. 分析: 两种方法: 1.两次bfs, 第一次求出最远的点, 第二次求该点的最远距离就是直径. 2.同hdu2196的第一次dfs, 求出每个节点到子树的最长距离和次 ...
- 在不是modelAttribute的情况下,如何保存页面输入值的方法(多行遍历)
<c:forEach var="prdRelInfo" items="${goodRelPrdList}" varStatus="s" ...
- 【03】使用 Firebug 调试 JavaScript
[03] 使用 Firebug 调试 JavaScript 描述 Firebug是一个非常强大的工具,可以帮助您发现代码发现错误的错误并解决错误. 在此我们使用Firebug来处理Javascript ...