zoukankan      html  css  js  c++  java
  • HDU4825/5536 [01 字典树/简单字典树更新]

    Xor Sum

    Time Limit: 1000 MS

    Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。你能证明人类的智慧么?

    Input

    输入包含若干组测试数据,每组测试数据包含若干行。
    输入的第一行是一个整数T(T < 10),表示共有T组数据。
    每组数据的第一行输入两个正整数N,M(<1=N,M<=100000),接下来一行,包含N个正整数,代表 Zeus 的获得的集合,之后M行,每行一个正整数S,代表 Prometheus 询问的正整数。所有正整数均不超过2^32。

    Output

    对于每组数据,首先需要输出单独一行”Case #?:”,其中问号处应填入当前的数据组数,组数从1开始计算。
    对于每个询问,输出一个正整数K,使得K与S异或值最大。

    Sample Input

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

    Sample Output

    Case #1: 4 3 Case #2: 4

    给出n个数,m次查询,每次查询输出异或值最大的那个数。

    01字典树,原来字典树还有这种操作。

    从高位向低位创建一棵字典树,val记录字典树的节点所代表的数值,查询的时候从高位开始向低位查询,每次贪心找到异或值最大的,输出该节点所代表的数值。

    #include "bits/stdc++.h"
    using namespace std;
    typedef long long LL;
    const int maxn = 100000 + 10;
    int ch[32*maxn][2];
     LL val[32*maxn];
    int sz;
    void init(){
         memset(ch[0], 0 ,sizeof(ch[0]));
         sz = 1;
     }
    void insert_01tree(LL a){
         int u = 0;
         for(int i = 31; i >= 0; i--) {
             int c = ((a>>i)&1);
             if(!ch[u][c]){
                 //新开节点,使得上一级的节点指向新开的节点
                 memset(ch[sz], 0, sizeof(ch[sz])); val[sz]=0;
                 ch[u][c] = sz++;
             }
             u = ch[u][c];
         }
         val[u] = a; //储存当前的值
    }
    LL query(LL a){
         int u = 0;
         for(int i = 31; i >= 0; i--){
             int c = ((a>>i)&1);
             if(ch[u][c^1]) u = ch[u][c^1];
             else u = ch[u][c];
         }
         return val[u];
     }
    int main(int argc, char const *argv[])
     {
         int T;
         int Kcase = 0;
         scanf("%d", &T);
         while (T--) {
             LL a; init();
             int N, M;
             scanf("%d%d", &N, &M);
             for (int i = 0; i < N; i++) {
                 scanf("%lld", &a);insert_01tree(a);
             }
             printf("Case #%d:
    ", ++Kcase);
             while (M--) {
                 scanf("%lld", &a);
                 printf("%lld
    ", query(a));
             }
         }
         return 0;
    }

    Chip Factory

    题意:

    给一个数组A,从A中找到两个数使得两个数的和和数组中的另外一个的异或最大

    枚举每两个数,将它们从字典树上删去,再查找和他们异或和最大的,然后在把两个数加到字典树上。用一个数组num记录每个数在字典树上的贡献,删去一个数只要把它的贡献减去就可以了。

    #include "bits/stdc++.h"
    using namespace std;
    typedef long long LL;
    const int maxn = 1e5;
    LL a[maxn], val[maxn];
    int ch[maxn][2], num[maxn];
    int sz = 1;
    void insert_01tree(LL x) {
        int u = 0;
        for (int i = 32; i >= 0; i--) {
            int c = ((x>>i)&1);
            if (!ch[u][c]) {
                memset(ch[sz], 0, sizeof(ch[sz]));
                num[sz] = 0; val[sz] = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c]; num[u]++; 
        }
        val[u] = x;
    }
    void updata(LL x, int d) {
        int u = 0;
        for (int i = 32; i >= 0; i--) {
            int c = ((x>>i)&1);
            u = ch[u][c];
            num[u] += d;
        }
    }
    LL query(LL x) {
        int u = 0; 
        for (int i = 32; i >= 0; i--) {
            int c = ((x>>i)&1);
            if(num[ch[u][c^1]] and ch[u][c^1]) u = ch[u][c^1];
            else u = ch[u][c];
        }
        return val[u];
    }
    void init() {
        memset(ch[0], 0, sizeof(ch[0]));
        memset(val, 0, sizeof(val));
        memset(num, 0, sizeof(num));
        sz = 1;
    }
    int main(int argc, char const *argv[])
    {
        int T;
        scanf("%d", &T);
        while (T--) {
            init();
            int N;
            LL maxx = 0;
            scanf("%d", &N);
            for (int i = 0; i < N; i++) 
                scanf("%lld", a+i), insert_01tree(a[i]);
            for (int i = 0; i < N; i++) {
                for (int j = i + 1; j < N; j++) {
                    updata(a[i], -1); updata(a[j], -1);
                    maxx = max(maxx ,(a[i]+a[j]) xor query(a[i]+a[j]));
                    updata(a[i], 1); updata(a[j], 1);
                }
            }
            printf("%lld
    ", maxx);
        }
        return 0;
    }
  • 相关阅读:
    spoj705
    bzoj2440
    spoj220
    bzoj2301
    hdu1695
    poj3294
    hdu3518
    poj3693
    函数
    样式
  • 原文地址:https://www.cnblogs.com/cniwoq/p/7345302.html
Copyright © 2011-2022 走看看