zoukankan      html  css  js  c++  java
  • BZOJ3689 异或之

    题面

    题目描述

    给定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
    

    【样例解释】

    1 xor 1 = 0 (A[1] xor A[2])
    1 xor 3 = 2 (A[1] xor A[3])
    1 xor 4 = 5 (A[1] xor A[4])
    1 xor 3 = 2 (A[2] xor A[3])
    1 xor 4 = 5 (A[2] xor A[4])
    3 xor 4 = 7 (A[3] xor A[4])
    前5小的数:0 2 2 5 5

    【数据范围】

    对于100%的数据,2 <= n <= 100000; 1 <= k <= min{250000, n*(n-1)/2};
    0 <= A[i] < 2^31

    题解

    堆 + trie.
    首先明确, trie树上可以找到一个数的xor第k大(小).
    我们把每个数的异或第(2)小先装进堆里面(异或第(1)小是自己异或自己, 不在题目考虑范围内), 每次取出堆头, 假设堆头是第(p)小, 则插入第(p + 1)小即可.
    注意应该取(2k)次, 因为每两次得到的结果是相同的.

    #include <cstdio>
    #include <cctype>
    #include <queue>
    
    namespace Zeonfai
    {
    	inline int getInt()
    	{
    		int a = 0, sgn = 1;
    		char c;
    		while(! isdigit(c = getchar()))
    			if(c == '-')
    				sgn *= -1;
    		while(isdigit(c))
    			a = a * 10 + c -'0', c = getchar();
    		return a * sgn;
    	}
    
    	inline void print(int a)
    	{
    		if(! a)
    			return;
    		print(a / 10);
    		putchar(a % 10 + '0');
    	}
    
    	inline void println(int a)
    	{
    		if(a < 0)
    			putchar('-'), a *= -1;
    		if(a == 0)
    			putchar('0');
    		print(a);
    		putchar(' ');
    	}
    }
    
    const int N = 100000;
    
    struct trieTree
    {
    	struct node
    	{
    		node *suc[2];
    		int cnt;
    
    		inline node()
    		{
    			suc[0] = suc[1] = NULL;
    			cnt = 0;
    		}
    	};
    
    	node *rt;
    
    	inline trieTree()
    	{
    		rt = new node;
    	}
    
    	inline void insert(int w)
    	{
    		node *u = rt;
    		for(int i = 30; ~ i; -- i)
    		{
    			int k = w >> i & 1;
    			if(u->suc[k] == NULL)
    				u->suc[k] = new node;
    			++ (u = u->suc[k])->cnt;
    		}
    	}
    
    	inline int query(int w, int k)
    	{
    		node *u = rt;
    		int res = 0;
    		for(int i = 30; ~ i; -- i)
    		{
    			int tmp = w >> i & 1;
    			if(u->suc[tmp] != NULL && u->suc[tmp]->cnt >= k)
    				u = u->suc[tmp];
    			else
    				k -= u->suc[tmp] == NULL ? 0 : u->suc[tmp]->cnt, u = u->suc[tmp ^ 1], res += 1 << i;
    		}
    		return res;
    	}
    }trie;
    
    struct record
    {
    	int id, k, w;
    
    	inline record(int _id, int _k ,int _w)
    	{
    		id = _id, k = _k, w = _w;
    	}
    
    	inline int friend operator <(record a, record b)
    	{
    		return a.w > b.w;
    	}
    };
    
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("BZOJ3689.in", "r", stdin);
    	#endif
    	using namespace Zeonfai;
    	int n = getInt(), k = getInt();
    	static int a[N];
    	for(int i = 0; i < n; ++ i)
    		trie.insert(a[i] = getInt());
    	static std::priority_queue<record> hp;
    	for(int i = 0; i < n; ++ i)
    		hp.push(record(i, 2, trie.query(a[i], 2)));
    	for(int i = 0; i < k << 1; ++ i)
    	{
    		record res = hp.top();
    		hp.pop();
    		if(i & 1)
    			println(res.w);
    		if(res.k < n)
    			hp.push(record(res.id, res.k + 1, trie.query(a[res.id], res.k + 1)));
    	}
    }
    
  • 相关阅读:
    78. Subsets
    93. Restore IP Addresses
    71. Simplify Path
    82. Remove Duplicates from Sorted List II
    95. Unique Binary Search Trees II
    96. Unique Binary Search Trees
    312. Burst Balloons
    程序员社交平台
    APP Store开发指南
    iOS框架搭建(MVC,自定义TabBar)--微博搭建为例
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/7115232.html
Copyright © 2011-2022 走看看