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:\n", ++Kcase);
         while (M--) {
             scanf("%lld", &a);
             printf("%lld\n", 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\n", maxx);
    }
    return 0;
}
时间: 2024-08-13 07:36:51

HDU4825/5536 [01 字典树/简单字典树更新]的相关文章

POJ 3468 A Simple Problem with Integers:线段树 简单操作 注意更新到区间而非叶节点

#include<cstdio> #include<iostream> using namespace std; #define Size 100000 struct Node { int L, R; long long Sum, Inc; int Mid() { return (L+R)/2; } }Tree[Size*3]; void CreatTree( int root, int L, int R )// 建区间树 { Tree[root].L = L; Tree[root

HDU 1247 简单字典树

Hat’s Words Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7359    Accepted Submission(s): 2661 Problem Description A hat’s word is a word in the dictionary that is the concatenation of exactly

统计难题(简单字典树)

字典树(讲解+模板) 又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高. 字典树跟字典很相似,当我们要查询一个单词是不是在字典中时,我们首先查询单词的第一个字母,之后确定了一个字母后,查找下一个字母,反复这种操作,直到找到单词,但是这种效率很低,在庞大的单词系统面前,则显得心塞了.

字典树简单知识及类实现

什么是trie树? ◇ trie树是一种用于快速检索的多叉树结构. ◇ 和二叉查找树不同,在trie树中,每个结点上并非存储一个元素. ◇ trie树把要查找的关键词看作一个字符序列.并根据构成关键词字符的先后顺序构造用于检索的树结构. ◇在trie树上进行检索类似于查阅英语词典. 一棵m度的trie树或者为空,或者由m棵m度的trie树构成. 例如,电子英文词典,为了方便用户快速检索英语单词,可以建立一棵trie树.例如词典由下面的单词构成:a.b.c.aa.ab.ac.ba.ca.aba.a

跳跃表,字典树(单词查找树,Trie树),后缀树,KMP算法,AC 自动机相关算法原理详细汇总

第一部分:跳跃表 本文将总结一种数据结构:跳跃表.前半部分跳跃表性质和操作的介绍直接摘自<让算法的效率跳起来--浅谈"跳跃表"的相关操作及其应用>上海市华东师范大学第二附属中学 魏冉.之后将附上跳跃表的源代码,以及本人对其的了解.难免有错误之处,希望指正,共同进步.谢谢. 跳跃表(Skip List)是1987年才诞生的一种崭新的数据结构,它在进行查找.插入.删除等操作时的期望时间复杂度均为O(logn),有着近乎替代平衡树的本领.而且最重要的一点,就是它的编程复杂度较同类

【转】B树、B-树、B+树、B*树、红黑树、 二叉排序树、trie树Double Array 字典查找树简介

B  树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: B树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中:否则,如果查询关键字比结点关键字小,就进入左儿子:如果比结点关键字大,就进入右儿子:如果左儿子或右儿子的指针为空,则报告找不到相应的关键字: 如果B树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树的搜索性

[转载]字典树(trie树)、后缀树

(1)字典树(Trie树) Trie是个简单但实用的数据结构,通常用于实现字典查询.我们做即时响应用户输入的AJAX搜索框时,就是Trie开始.本质上,Trie是一颗存储多个字符串的树.相邻节点间的边代表一个字符,这样树的每条分支代表一则子串,而树的叶节点则代表完整的字符串.和普通树不同的地方是,相同的字符串前缀共享同一条分支.还是例子最清楚.给出一组单词,inn, int, at, age, adv, ant, 我们可以得到下面的Trie: 可以看出: 每条边对应一个字母. 每个节点对应一项前

Hash树(散列树)和Trie树(字典树、前缀树)

1.Hash树 理想的情况是希望不经过任何比较,一次存取便能得到所查的记录, 那就必须在记的存储位置和它的关键字之间建立一个确定的对应关系f,使每个关键字和一个唯一的存储位置相对应.因而在查找时,只要根据这个对应关系f找到 给定值K的像f(K).由此,不需要进行比较便可直接取得所查记录.在此,我们称这个对应关系为哈希(Hash)函数,按这个思想建立的表为哈希表. 在哈希表中对于不同的关键字可能得到同一哈希地址,这种现象称做冲突.在一般情况下,冲突只能尽可能地减少,而不能完全避免.因为哈希函数是从

trie树(字典树)

1. trie树,又名字典树,顾名思义,它是可以用来作字符串查找的数据结构,它的查找效率比散列表还要高. trie树的建树: 比如有字符串"ab" ,"adb","adc"   可以建立字典树如图: 树的根节点head不存储信息,它有26个next指针,分别对应着字符a,b,c等.插入字符串ab时,next['a'-'a']即next[0]为空,这是申请一个结点放在next[0]的位置,插入字符串db时,next['d'-'a']即next[3]