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图及其应用.当然这些都是比较高级的数据结构和算法,而这里面最常用和最熟 ...
随机推荐
- gulp自动化构建工具使用
gulpfile.js: var gulp = require("gulp"); var imagemin = require("gulp-imagemin") ...
- vba,自定义公式,农历互转公历,excel ,wps
'vba 模块内容如下 自定义公式 '公历转农历模块 '原创:互联网 '修正: '// 农历数据定义 // '先以 H2B 函数还原成长度为 18 的字符串,其定义如下: '前12个字节代表1-12月 ...
- 51nod 1096 距离之和最小(水题日常)
基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 X轴上有N个点,求X轴上一点使它到这N个点的距离之和最小,输出这个最小的距离之和. Input 第1行:点的数量 ...
- 使用sersync实现实时同步实战
场景需求: 应用程序会在机器192.168.2.2 /usr/local/news目录中生成一些数据文件,现在需要实时同步到主机192.168.3.3/usr/local/www/cn/news中,同 ...
- jmeter 接口测试简介
前言: 本文主要针对http接口进行测试,使用Jmeter工具实现. Jmter工具设计之初是用于做性能测试的,它在实现对各种接口的调用方面已经做的比较成熟,因此,本次直接使用Jmeter工具来完成对 ...
- Web前端基础怎么学? JavaScript、html、css知识架构图
以前开发者只要掌握 HTML.CSS.JavaScript 三驾马车就能胜任一份前端的工作了.而现在除了普通的编码以外,还要考虑如何性能优化,如何跨端.跨平台实现功能,尤其是 AI.5G 技术的来临, ...
- AspNetCore容器化(Docker)部署(一) —— 入门
一.docker注册安装 Windows Docker Desktop https://www.docker.com/products/docker-desktop Linux Docker CE h ...
- 微信小程序入口场景的问题整理与相关解决方案
前言 最近一段时间都在做小程序. 虽然是第二次开发小程序,但是上次做小程序已经是一年前的事了,所以最终还是被坑得死去活来. 这次是从零开始开发一个小程序,其实除了一些莫名其妙的兼容性问题,大多数坑点都 ...
- Shell替换数组元素之间的间隔符号
Shell中的数组是这样表示的: arr=(1,2,3,4,5) 它们数组元素的间隔符号为逗号,如果我相把逗号替换为加号: echo ${arr//,/+} 输出: 1+2+3+4+5 这个表达式是我 ...
- POJ-2442-Sequence(二叉堆)
POJ-2442 Description Given m sequences, each contains n non-negative integer. Now we may select one ...