[BZOJ4103][Thu Summer Camp 2015]异或运算

Posted xjr_01

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ4103][Thu Summer Camp 2015]异或运算相关的知识,希望对你有一定的参考价值。

[BZOJ4103][Thu Summer Camp 2015]异或运算

试题描述

给定长度为n的数列X={x1,x2,...,xn}和长度为m的数列Y={y1,y2,...,ym},令矩阵A中第i行第j列的值Aij=xi xor  yj,每次询问给定矩形区域i∈[u,d],j∈[l,r],找出第k大的Aij。

输入

第一行包含两个正整数n,m,分别表示两个数列的长度

第二行包含n个非负整数xi
第三行包含m个非负整数yj
第四行包含一个正整数p,表示询问次数
随后p行,每行均包含5个正整数,用来描述一次询问,每行包含五个正整数u,d,l,r,k,含义如题意所述。

输出

共p行,每行包含一个非负整数,表示此次询问的答案。

输入示例

3 3
1 2 4
7 6 5
3
1 2 1 2 2
1 2 1 3 4
2 3 2 3 4

输出示例

6
5
1

数据规模及约定

对于100%的数据,0<=Xi,Yj<2^31,

1<=u<=d<=n<=1000,

1<=l<=r<=m<=300000,

1<=k<=(d-u+1)*(r-l+1),

1<=p<=500

题解

注意到 n 很小,所以我们可以一维暴力,另一维可持久化 trie。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;

int read() {
	int x = 0, f = 1; char c = getchar();
	while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); }
	return x * f;
}

#define maxn 1010
#define maxm 300010
#define maxnode 9600010
#define bin 30
#define oo 2147483647

int n, m, X[maxn];

int ToT, rt[maxm], ch[maxnode][2], siz[maxnode];
void update(int& y, int x, int p, int val) {
	siz[y = ++ToT] = siz[x] + 1;
	if(p < 0) return ;
	memcpy(ch[y], ch[x], sizeof(ch[x]));
	update(ch[y][val>>p&1], ch[x][val>>p&1], p - 1, val);
	return ;
}
int lrt[maxn], rrt[maxn];
int qkth(int xl, int xr, int yl, int yr, int K) {
	for(int i = xl; i <= xr; i++) lrt[i] = rt[yl-1], rrt[i] = rt[yr];
	int ans = 0;
	for(int i = bin; i >= 0; i--) {
		int tmp = 0;
		for(int j = xl; j <= xr; j++)
			tmp += siz[ch[rrt[j]][X[j]>>i&1^1]] - siz[ch[lrt[j]][X[j]>>i&1^1]];
		if(K <= tmp) {
			for(int j = xl; j <= xr; j++)
				lrt[j] = ch[lrt[j]][X[j]>>i&1^1],
				rrt[j] = ch[rrt[j]][X[j]>>i&1^1];
			ans = ans << 1 | 1;
		}
		else {
			K -= tmp;
			for(int j = xl; j <= xr; j++)
				lrt[j] = ch[lrt[j]][X[j]>>i&1],
				rrt[j] = ch[rrt[j]][X[j]>>i&1];
			ans <<= 1;
		}
	}
	return ans;
}

int main() {
	n = read(); m = read();
	for(int i = 1; i <= n; i++) X[i] = read();
	for(int i = 1; i <= m; i++) update(rt[i], rt[i-1], bin, read());
	
	int q = read();
	while(q--) {
		int xl = read(), xr = read(), yl = read(), yr = read(), k = read();
		printf("%d\n", qkth(xl, xr, yl, yr, k));
	}
	
	return 0;
}

 

以上是关于[BZOJ4103][Thu Summer Camp 2015]异或运算的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4103[Thu Summer Camp 2015]异或运算 可持久化Trie树

bzoj4103[Thu Summer Camp 2015]异或运算(可持久化trie树)

bzoj4103 [Thu Summer Camp 2015]异或运算(可持久化trie)

bzoj4103[Thu Summer Camp 2015]异或运算 可持久化Trie树

BZOJ4896 [Thu Summer Camp2016]补退选

bzoj:4105: [Thu Summer Camp 2015]平方运算