HDU 5536 01Trie树
2015-11-04 23:00
295 查看
HDU 5536
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5536
题意:
1000个数里面,选三个下标不同的数构成函数(ai+aj)^ak。
求这个函数的最大值。
思路:
复现并没有做出来。
暴力竟然能过。
01Trie的话本质是贪心,把所有数按照二进制插入Trie里,枚举i和j,然后每次用32的常数级查询就能得到对应最大值。
1)即根据异或性质,如果两个数二进制表示上的相同位置数字相同则异或值为0,否则为1;
2)2^n > 2^1 + 2^2 + … + 2^(n-1)(这里表示幂次)。
源码:
暴力版:
01Trie版:
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5536
题意:
1000个数里面,选三个下标不同的数构成函数(ai+aj)^ak。
求这个函数的最大值。
思路:
复现并没有做出来。
暴力竟然能过。
01Trie的话本质是贪心,把所有数按照二进制插入Trie里,枚举i和j,然后每次用32的常数级查询就能得到对应最大值。
1)即根据异或性质,如果两个数二进制表示上的相同位置数字相同则异或值为0,否则为1;
2)2^n > 2^1 + 2^2 + … + 2^(n-1)(这里表示幂次)。
源码:
暴力版:
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <cstdlib> #include <string> #include <vector> using namespace std; #define LL long long const int MAXN = 1000 + 5; LL d[MAXN]; vector<int>two[35]; LL max2(LL a) { LL ans = 1; while(ans <= a) ans = ans << 1; return ans; } int main() { int T; scanf("%d", &T); while(T--){ int n; scanf("%d", &n); for(int i = 0 ; i < n ; i++) scanf("%I64d", &d[i]); LL ans = 0; for(int i = 0 ; i < n ; i++){ for(int j = i + 1 ; j < n ; j++){ for(int k = j + 1 ; k < n ; k++){ ans = max(ans, (d[i] + d[j]) ^ d[k]); ans = max(ans, (d[i] + d[k]) ^ d[j]); ans = max(ans, (d[j] + d[k]) ^ d[i]); } } } printf("%I64d\n", ans); } return 0; }
01Trie版:
#include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> #include <iostream> #include <string> #include <vector> using namespace std; const int MAXN = 100000 * 2 + 5; int cnt; struct Trie { int son[2]; int num[2]; void init(){memset(son, 0, sizeof(son)); memset(num, 0, sizeof(num));} }trie[MAXN * 2]; int d[1000 + 5]; void ins(int a) { int u = 0; for(int i = 30 ; i >= 0 ; i--){ int mark; if(a & (1 << i)) mark = 1; else mark = 0; if(trie[u].son[mark] == 0){ trie[u].son[mark] = ++cnt; trie[u].num[mark] = 1; } else{ trie[u].num[mark]++; } u = trie[u].son[mark]; } } void del(int a) { int u = 0; for(int i = 30 ; i >= 0 ; i--){ int mark; if(a & (1 << i)) mark = 1; else mark = 0; trie[u].num[mark]--; u = trie[u].son[mark]; } } int query(int a) { int ans = 0; int u = 0; for(int i = 30 ; i >= 0 ; i--){ int mark; if(a & (1 << i)) mark = 1; else mark = 0; // if(mark == 0){ if(trie[u].num[mark^1] && trie[u].son[mark^1]){ u = trie[u].son[mark^1]; ans += 1 << i; } else{ u = trie[u].son[mark]; } // } // else{ // if(trie[u].num[mark^1] && trie[u].son[mark^1]){ // u = trie[u].son[mark^1]; // ans += 1 << i; // } // else{ // u = trie[u].son[mark]; // } // } } return ans; } int main() { int T; scanf("%d", &T); while(T--){ int n; scanf("%d", &n); for(int i = 0 ; i < n ; i++) scanf("%d", &d[i]); // sort(d, d + n); cnt = 0; // for(int i = 0 ; i < MAXN * 2 ; i++) trie[i].init(); for(int i = 0 ; i < n ; i++) ins(d[i]); int ans = 0; for(int i = n - 1 ; i >= 0 ; i--){ del(d[i]); for(int j = i - 1 ; j >= 0 ; j--){ del(d[j]); ans = max(ans, query(d[i] + d[j])); ins(d[j]); } ins(d[i]); } for(int i = 0 ; i <= cnt ; i++) trie[i].init(); printf("%d\n", ans); } return 0; }
相关文章推荐
- Java 日志管理最佳实践
- 多重循环程序(嵌套循环)一
- 微积分的学习
- 7.1面向对象概述
- Nginx基础入门之nginx编译参数说明介绍
- 面向对象编程以及Python面向对象
- 对于AttributeError: ‘module’ object has no attribute ‘AF_INET
- 爬爬爬之路:OC语言(八) 属性 KVC简单介绍
- Linux Rsync
- NOIP2013 Day1 T3 货车运输
- c++对文件操作
- C#学习单向链表和接口 IList<T>
- Operating System: Three Easy Pieces --- Concurrency: An Introduction (Note)
- noi2015的回忆和教训
- 每天一道算法题(40)——组成的最小数字
- 客户端读取HDFS中的数据
- 记录上个表单提交内容的例子
- 【我的故事】写在一万(怀带着谴责激励自己)
- 每天一道算法题(40)——组成的最小数字
- 在双击控件进入到程序代码编辑界面后,没写东西不影响运行,但删除后报错