zoukankan      html  css  js  c++  java
  • ACM学习历程—HDU 5536 Chip Factory(xor && 字典树)

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

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

    首先n1000,暴力理论上是不行的。

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

    于是可以考虑枚举ij,然后匹配k

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

    然后枚举s[i]s[j],由于ijk互不相等,于是先从字典树里面删掉s[i]s[j],然后对s[i]+s[j]这个数在字典树中匹配,自然是高位如果能xor1就匹配,不能就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
    ", ans);
    }
    
    int main()
    {
        //freopen("test.in", "r", stdin);
        int T;
        scanf("%d", &T);
        for (int times = 0; times < T; ++times)
        {
            input();
            work();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    架设证书服务器 及 让IIS启用HTTPS服务
    实验二. 使用LoadRunner进行压力测试
    loadrunner简单使用——HTTP,WebService,Socket压力测试脚本编写
    康威定律,可以学习一下
    各国iPhone5系列最新裸机价格
    .yml是什么文件
    win32多线程程序设计笔记(第五章)
    kvm libvirt: hostdev passthrough support 解决加密狗冲突问题
    九度OnlineJudge之1023:EXCEL排序
    [置顶] Android开发之XML文件的解析
  • 原文地址:https://www.cnblogs.com/andyqsmart/p/4965024.html
Copyright © 2011-2022 走看看