BZOJ4103 [Thu Summer Camp 2015]异或运算 【可持久化trie树】
题目链接
题解
一眼看过去是二维结构,实则未然需要树套树之类的数据结构
区域异或和,就一定是可持久化\(trie\)树
观察数据,\(m\)非常大,而\(n\)和\(p\)比较小,甚至可以每次询问都枚举\(x_i\)
所以我们可以考虑对\(y_i\)建\(trie\),每次询问取出对应区间的\(x_i\)在对应区间的\(trie\)树中跑
多点询问和单点询问时类似的,只不过它们会分开走
我们只需每次记录每个\(x_i\)所在的节点
对于每一层,统计一下能异或出多少\(1\),如果\(\le k\),每个\(x_i\)往能异或出\(1\)的方向走,否则走另一边,并令\(k\)减去这些数
复杂度\(O(31m + 31qn)\)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 300005,B = 30,maxm = 10000005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int bin[50],n,m;
int a[1005],b[maxn],rt[maxn],cnt;
int ch[maxm][2],sum[maxm];
int ins(int x,int v){
int u,tmp;
u = tmp = ++cnt;
for (int i = B; ~i; i--){
ch[u][0] = ch[v][0];
ch[u][1] = ch[v][1];
sum[u] = sum[v] + 1;
int t = bin[i] & x; t >>= i;
v = ch[v][t];
u = ch[u][t] = ++cnt;
}
sum[u] = sum[v] + 1;
return tmp;
}
int atu[1005],atv[1005];
int query(int u,int v,int l,int r,int k){
int ans = 0;
for (int i = l; i <= r; i++) atu[i] = u,atv[i] = v;
for (int i = B; ~i; i--){
int cnt = 0;
for (int j = l; j <= r; j++){
int x = atu[j],y = atv[j],t = bin[i] & a[j]; t >>= i;
cnt += sum[ch[x][t ^ 1]] - sum[ch[y][t ^ 1]];
}
if (cnt >= k){
ans += bin[i];
for (int j = l; j <= r; j++){
int x = atu[j],y = atv[j],t = bin[i] & a[j]; t >>= i;
atu[j] = ch[x][t ^ 1];
atv[j] = ch[y][t ^ 1];
}
}
else {
k -= cnt;
for (int j = l; j <= r; j++){
int x = atu[j],y = atv[j],t = bin[i] & a[j]; t >>= i;
atu[j] = ch[x][t];
atv[j] = ch[y][t];
}
}
}
return ans;
}
int main(){
bin[0] = 1; for (int i = 1; i <= 30; i++) bin[i] = bin[i - 1] << 1;
n = read(); m = read();
for (int i = 1; i <= n; i++) a[i] = read();
for (int i = 1; i <= m; i++){
b[i] = read();
rt[i] = ins(b[i],rt[i - 1]);
}
int p = read(),u,d,l,r,k;
while (p--){
u = read(); d = read(); l = read(); r = read(); k = read();
printf("%d\n",query(rt[r],rt[l - 1],u,d,k));
}
return 0;
}
BZOJ4103 [Thu Summer Camp 2015]异或运算 【可持久化trie树】的更多相关文章
- [BZOJ4103][Thu Summer Camp 2015]异或运算 可持久化Trie树
4103: [Thu Summer Camp 2015]异或运算 Time Limit: 20 Sec Memory Limit: 512 MB Description 给定长度为n的数列X={x1 ...
- 【bzoj4103】[Thu Summer Camp 2015]异或运算 可持久化trie树
Description 给定长度为n的数列X={x1,x2,...,xn}和长度为m的数列Y={y1,y2,...,ym},令矩阵A中第i行第j列的值Aij=xi xor yj,每次询问给定矩形区域i ...
- BZOJ 4103: [Thu Summer Camp 2015]异或运算 可持久化trie
开始想了一个二分+可持久化trie验证,比正解多一个 log 仔细思考,你发现你可以直接按位枚举,然后在可持久化 trie 上二分就好了. code: #include <bits/stdc++ ...
- bzoj4103 [Thu Summer Camp 2015]异或运算(可持久化trie)
内存限制:512 MiB 时间限制:1000 ms 题目描述 给定长度为n的数列X={x1,x2,...,xn}和长度为m的数列Y={y1,y2,...,ym},令矩阵A中第i行第j列的值Aij=xi ...
- bzoj4103: [Thu Summer Camp 2015]异或运算
对于每个询问暴力枚举x~y,然后在Trie去找第k大,开始我写了个二分答案然后算比当前答案大的个数,打了个第10个点的表就跑出19s+比bzoj垫底还慢4s+ 然而不用二分,直接1000个点一起在树上 ...
- 【BZOJ 4103】 [Thu Summer Camp 2015]异或运算 可持久化01Trie
我们观察数据:树套树 PASS 主席树 PASS 一层一个Trie PASS 再看,异或!我们就把目光暂时定在01Tire然后我们发现,我们可以带着一堆点在01Trie上行走,因为O(n*q* ...
- 【BZOJ 4103】 4103: [Thu Summer Camp 2015]异或运算 (可持久化Trie)
4103: [Thu Summer Camp 2015]异或运算 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 474 Solved: 258 De ...
- [BZOJ 4103] [Thu Summer Camp 2015] 异或运算 【可持久化Trie】
题目链接:BZOJ - 4103 题目分析 THUSC滚粗之后一直没有写这道题,从来没写过可持久化Trie,发现其实和可持久化线段树都是一样的.嗯,有些东西就是明白得太晚. 首先Orz ZYF-ZYF ...
- [十二省联考2019]异或粽子——可持久化trie树+堆
题目链接: [十二省联考2019]异或粽子 求前$k$大异或区间,可以发现$k$比较小,我们考虑找出每个区间. 为了快速得到一个区间的异或和,将原序列做前缀异或和. 对于每个点作为右端点时,我们维护出 ...
随机推荐
- 「日常训练」Woodcutters(Codeforces Round 303 Div.2 C)
这题惨遭被卡..卡了一个小时,太真实了. 题意与分析 (Codeforces 545C) 题意:给定\(n\)棵树,在\(x\)位置,高为\(h\),然后可以左倒右倒,然后倒下去会占据\([x-h,x ...
- Python里//与/的区别?
1.Python里面//的作用是除法取整,也就是直接取整数部分 例如:5//6=0; 56//3=18 2.而/的作用是直接进行常规的除法运算 例如:56/8=7 程序运算实例如下:
- Codeforces Round #495 (Div. 2) Sonya and Matrix
正常没有正方形的限制下,值为i的点个数4i 那么从0开始遍历,第一个不为4i的值就是min(x, y) 由于对称性我们姑且令x为这个值 我们先列举n*m=t的各种情况 对于一对n, m.我们已经知道n ...
- Java异常层次结构
1. 如果是不可查异常(unchecked exception),即Error.RuntimeException或它们的子类,那么可以不使用throws关键字来声明要抛出的异常,编译仍能顺利通过,但在 ...
- 259 [LeetCode] 3Sum Smaller 三数之和较小值
题目: Given an array of n integers nums and a target, find the number of index triplets i, j, k with 0 ...
- addeventlistener和attachevent
区别: 1.ie8及以下版本前者无效,只能使用后者: 2,关于第三个参数,如果是true则捕获状态触发,为false;则为冒泡状态触发 何为冒泡,何为捕获? 这就好比捕鱼,冒泡吗,鱼向上吐泡泡,所以当 ...
- Python中的slice操作
Python中slice操作的完整语法: # i默认是0 # j默认是len(S) # k的步长,默认为+1 S[i:j:k] 其中i,j,k都可以是负数: 若i < 0或者k<0,等价于 ...
- “小葵日记”API接口文档
"小葵日记"项目API接口文档 时间:2017/10/31 (1)用户登录[待完成] POST:127.0.0.1/index/user/login data 数据别称 数据名 数 ...
- LintCode-54.转换字符串到整数
转换字符串到整数 实现atoi这个函数,将一个字符串转换为整数.如果没有合法的整数,返回0.如果整数超出了32位整数的范围,返回INT_MAX(2147483647)如果是正整数,或者INT_MIN( ...
- LintCode-374.螺旋矩阵
螺旋矩阵 给定一个包含 m x n 个要素的矩阵,(m 行, n 列),按照螺旋顺序,返回该矩阵中的所有要素. 样例 给定如下矩阵: [ [ 1, 2, 3 ], [ 4, 5, 6 ...