【bzoj3689】异或之 可持久化Trie树+堆

题目描述

给定n个非负整数A[1], A[2], ……, A[n]。
对于每对(i, j)满足1 <= i < j <= n,得到一个新的数A[i] xor A[j],这样共有n*(n-1)/2个新的数。求这些数(不包含A[i])中前k小的数。
注:xor对应于pascal中的“xor”,C++中的“^”。

输入

第一行2个正整数 n,k,如题所述。
以下n行,每行一个非负整数表示A[i]。

输出

共一行k个数,表示前k小的数。

样例输入

4 5
1
1
3
4

样例输出

0 2 2 5 5


题解

可持久化Trie树+堆,和 bzoj2006 差不多

那道题要求的是区间内数的最大值,所以使用了ST表;这道题需要求区间内数与某数的最大异或和,所以需要使用可持久化Trie树。

具体实现:维护一个结构体存储5个变量t、l、r、p、v,分别代表:两个数中的第一个、两个数中的第二个的取值范围的左端、两个数中的第二个的取值范围的右端、最大异或和的第二个数的位置、最大异或和。将初始区间扔进以最大异或和为关键字的大根堆里,每次取出一个结构体,把v加到答案中,并计算(t,l,p-1)和((t,p+1,r),再把它们扔回堆中。

时间复杂度$O(k\log n)$

#include <cstdio>
#include <queue>
#define N 200010
#define M 6000010
using namespace std;
struct data
{
	int t , l , r , p , v;
	data() {}
	data(int t0 , int l0 , int r0 , int p0 , int v0) {t = t0 , l = l0 , r = r0 , p = p0 , v = v0;}
	bool operator<(const data a)const {return v > a.v;}
}tmp;
priority_queue<data> q;
int a[N] , c[2][M] , si[M] , tag[M] , root[N] , tot;
int insert(int x , int p , int v)
{
	int i , y = ++tot , r = y;
	bool t;
	for(i = 1 << 30 ; i ; i >>= 1)
		t = v & i , c[t ^ 1][y] = c[t ^ 1][x] , c[t][y] = ++tot , x = c[t][x] , y = c[t][y] , si[y] = si[x] + 1;
	tag[y] = p;
	return r;
}
int query(int x , int y , int v)
{
	int i;
	bool t;
	for(i = 1 << 30 ; i ; i >>= 1)
	{
		t = v & i;
		if(si[c[t][y]] - si[c[t][x]]) y = c[t][y] , x = c[t][x];
		else y = c[t ^ 1][y] , x = c[t ^ 1][x];
	}
	return tag[y];
}
int main()
{
	int n , k , i , d;
	scanf("%d%d" ,  &n , &k);
	for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]) , root[i] = insert(root[i - 1] , i , a[i]);
	for(i = 1 ; i < n ; i ++ ) d = query(root[i] , root[n] , a[i]) , q.push(data(i , i + 1 , n , d , a[d] ^ a[i]));
	while(k -- )
	{
		tmp = q.top() , q.pop() , printf("%d " , tmp.v);
		if(tmp.p > tmp.l) d = query(root[tmp.l - 1] , root[tmp.p - 1] , a[tmp.t]) , q.push(data(tmp.t , tmp.l , tmp.p - 1 , d , a[d] ^ a[tmp.t]));
		if(tmp.r > tmp.p) d = query(root[tmp.p] , root[tmp.r] , a[tmp.t]) , q.push(data(tmp.t , tmp.p + 1 , tmp.r , d , a[d] ^ a[tmp.t]));
	}
	return 0;
}

 

 

posted @ 2017-07-04 09:12  GXZlegend  阅读(707)  评论(0编辑  收藏  举报