ACM学习历程—HDU 5536 Chip Factory(xor && 字典树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5536

题目大意是给了一个序列,求(si+sj)^sk的最大值。

首先n有1000,暴力理论上是不行的。

此外题目中说大数据只有10组,小数据最多n只有100。(那么c*n^2的复杂度应该差不多)

于是可以考虑枚举i和j,然后匹配k。

于是可以先把所有s[k]全部存进一个字典树,

然后枚举s[i]和s[j],由于i、j、k互不相等,于是先从字典树里面删掉s[i]和s[j],然后对s[i]+s[j]这个数在字典树中匹配,自然是高位如果能xor出1就匹配,不能就0。这个和普通的xor两个匹配最值是一样的。

匹配完,再把s[i]和s[j]加回去。

复杂度O(15n*n)左右.

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#include <queue>
#include <vector>
#define LL long long

using namespace std;

//求n个数中取出两个数能xor的最大值
//Trie Tree字典树
//len*n, len为数的二进制最大长度
const int maxN = 1005;
const int len = 31;//len表示数的二进制最大长度
struct Trie
{
    int next[2];
}tree[maxN*len];
int num[maxN*len];
int cnt, n, a[maxN];

void initTree()
{
    cnt = 0;
    memset(tree, -1, sizeof(tree));
    memset(num, 0, sizeof(num));
}

void add(int x)
{
    int now = 0;
    bool k;
    for (int i = len; i >= 0; i--)
    {
        k = x&(1<<i);
        if (tree[now].next[k] == -1)
            tree[now].next[k] = ++cnt;
        now = tree[now].next[k];
        num[now]++;
    }
}

void del(int x)
{
    int now = 0;
    bool k;
    for (int i = len; i >= 0; i--)
    {
        k = x&(1<<i);
        now = tree[now].next[k];
        num[now]--;
    }
}

//返回当前数中能和x合成最大数的数
int query(int x)
{
    int v = 0, now = 0;
    bool k;
    for (int i = len; i >= 0; i--)
    {
        k = x&(1<<i);
        if (tree[now].next[!k] != -1 && num[tree[now].next[!k]] != 0)
            k = !k;
        v = v|(k<<i);
        now = tree[now].next[k];
    }
    return v;
}

void input()
{
    initTree();
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
    {
        scanf("%d", &a[i]);
        add(a[i]);
    }
}

int myMax(int x, int y)
{
    if (x == -1) return y;
    else return max(x, y);
}

void work()
{
    int ans = -1, tmp;
    for (int i = 0; i < n; ++i)
    {
        for (int j = i+1; j < n; ++j)
        {
            del(a[i]); del(a[j]);
            tmp = a[i]+a[j];
            //cout << "****" << tmp << " " << query(tmp) << endl;
            ans = myMax(ans, tmp^query(tmp));
            add(a[i]); add(a[j]);
        }
    }
    printf("%d\n", ans);
}

int main()
{
    //freopen("test.in", "r", stdin);
    int T;
    scanf("%d", &T);
    for (int times = 0; times < T; ++times)
    {
        input();
        work();
    }
    return 0;
}

时间: 2024-10-12 12:18:18

ACM学习历程—HDU 5536 Chip Factory(xor && 字典树)的相关文章

HDU 5536 Chip Factory(字典树)

题目戳这 题意:给你n个数,从中选出三个数a,b,c,然后(a+b)^c,这个式子的值是最大的. 思路:如果来三个for循环,果断TLE,所以想到了字典树,就是先把所有的数字都插进去,在查询的时候就先把确定了的那两个数字删掉,然后在字典树中求出异或的最大值,得到结果后,再把两个数字插回去. P.S.一开始我的数组开到了45*10^5+10,然后他给我TLE,然后当我把数组开到10^5+10的时候,A了···········,居然是数组爆我时间了,我勒个擦. #include<stdio.h>

ACM学习历程—Hihocoder 1289 403 Forbidden(字典树 || (离线 &amp;&amp; 排序 &amp;&amp; 染色))

http://hihocoder.com/problemset/problem/1289 这题是这次微软笔试的第二题,过的人比第三题少一点,这题一眼看过去就是字符串匹配问题,应该可以使用字典树解决.不过当时还有一个想法就是离线处理,把所有查询进行排序,然后用rule去匹配查询,进行染色处理,而且每个查询只进行一次染色.事实证明,如果比赛的时候采用第二种方法应该能拿全分,但是我用了第一种方法,导致只拿了10分...因为我没有考虑同一个rule出现两次的情况,但是字典树中会直接被后面的rule覆盖,

ACM学习历程—HDU 4726 Kia&#39;s Calculation( 贪心&amp;&amp;计数排序)

DescriptionDoctor Ghee is teaching Kia how to calculate the sum of two integers. But Kia is so careless and alway forget to carry a number when the sum of two digits exceeds 9. For example, when she calculates 4567+5789, she will get 9246, and for 12

ACM学习历程—HDU 5023 A Corrupt Mayor&#39;s Performance Art(广州赛区网赛)(线段树)

Problem Description Corrupt governors always find ways to get dirty money. Paint something, then sell the worthless painting at a high price to someone who wants to bribe him/her on an auction, this seemed a safe way for mayor X to make money. Becaus

HDU 5536 Chip Factory 字典树+贪心

给你n个数,a1....an,求(ai+aj)^ak最大的值,i不等于j不等于k 思路:先建字典树,暴力i,j每次删除他们,然后贪心找k,再恢复i,j,每次和答案取较大的,就是答案,有关异或的貌似很多都用字典树,也是醉了 /*Problem : 5536 ( Chip Factory ) Judge Status : Accepted RunId : 15506230 Language : G++ Author : qianbi08*/ #include<iostream> #include&

2015ACM/ICPC亚洲区长春站 J hdu 5536 Chip Factory

Chip Factory Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 368    Accepted Submission(s): 202 Problem Description John is a manager of a CPU chip factory, the factory produces lots of chips

hdu 5536 Chip Factory 字典树+bitset 铜牌题

Chip Factory Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1842    Accepted Submission(s): 833 Problem Description John is a manager of a CPU chip factory, the factory produces lots of chip

ACM学习历程—HDU 3915 Game(Nim博弈 &amp;&amp; xor高斯消元)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3915 题目大意是给了n个堆,然后去掉一些堆,使得先手变成必败局势. 首先这是个Nim博弈,必败局势是所有xor和为0. 那么自然变成了n个数里面取出一些数,使得xor和为0,求取法数. 首先由xor高斯消元得到一组向量基,但是这些向量基是无法表示0的. 所以要表示0,必须有若干0来表示,所以n-row就是消元结束后0的个数,那么2^(n-row)就是能组成0的种数. 对n==row特判一下. 代码:

ACM学习历程—HDU 3949 XOR(xor高斯消元)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3949 题目大意是给n个数,然后随便取几个数求xor和,求第k小的.(重复不计算) 首先想把所有xor的值都求出来,对于这个规模的n是不可行的. 然后之前有过类似的题,求最大的,有一种方法用到了线性基. 那么线性基能不能表示第k大的呢? 显然,因为线性基可以不重复的表示所有结果.它和原数组是等价的. 对于一个满秩矩阵 100000 010000 001000 000100 000010 000001