hdu 5715 XOR 游戏(trie)
2016-05-29 22:52
274 查看
看这里
dp[i][k] = max(min(dp[j][k-1], s[j] ^ s[i]),dp[i][k])。
二分答案val,则dp[j][k-1]肯定要满足大于等于val,并且s[j] ^ s[i] >= val才能够转移。
在trie树上找最大的 s[j] ^ s[i]。。
dp[i][k] = max(min(dp[j][k-1], s[j] ^ s[i]),dp[i][k])。
二分答案val,则dp[j][k-1]肯定要满足大于等于val,并且s[j] ^ s[i] >= val才能够转移。
在trie树上找最大的 s[j] ^ s[i]。。
#include <bits/stdc++.h> #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define LL long long #define ULL unsigned long long #define pii pair<int, int> #define MP make_pair #define ls i << 1 #define rs ls | 1 #define md (ll + rr >> 1) #define lson ll, md, ls #define rson md + 1, rr, rs #define inf 0x3f3f3f3f #define mod 1000000007 #define eps 1e-8 #define N 10010 #define M 200020 struct trie{ int son[N*32][2], tim[N*32], tot; void init(){ son[0][0] = son[0][1] = tot = 0; tim[0] = 1; } void insert(int val){ int t = 0; for(int i = 30; i >= 0; --i){ int c = (val >> i) & 1; if(son[t][c] == 0){ son[t][c] = ++tot; son[tot][0] = son[tot][1] = tim[tot] = 0; } t = son[t][c]; tim[t]++; } } void del(int val){ int t = 0; for(int i = 30; i >= 0; --i){ int c = (val >> i) & 1; int tt = t; t = son[t][c]; tim[t]--; if(tim[t] == 0){ son[tt][c] = 0; break; } } } int query(int val){ int ret = 0, t = 0; for(int i = 30; i >= 0; --i){ int c = (val >> i) & 1; if(son[t][c^1]){ t = son[t][c^1]; ret += (1 << i); } else { t = son[t][c]; } } return ret; } }tree[15]; int n, m, K, ans, a , s ; int dp [15]; bool check(int val){ dp[0][0] = 1; for(int i = 0; i <= m; ++i) tree[i].init(); tree[0].insert(0); for(int i = 1; i <= n; ++i){ for(int j = 1; j <= m; ++j){ dp[i][j] = 0; if(i > K && dp[i- K - 1][j-1]) tree[j-1].del(s[i- K - 1]); } for(int j = m; j >= 1; --j){ if(tree[j-1].query(s[i]) >= val){ dp[i][j] = 1; tree[j].insert(s[i]); } } } return dp [m]; } int main(){ int cas, kk = 0; scanf("%d", &cas); while(cas--){ scanf("%d%d%d", &n, &m, &K); for(int i = 1; i <= n; ++i) scanf("%d", &a[i]), s[i] = s[i-1] ^ a[i]; int L = 0, R = 1000000010; while(L < R){ int mid = (L + R) >> 1; if(check(mid)) ans = mid, L = mid + 1; else R = mid; } printf("Case #%d:\n%d\n", ++kk, ans); } return 0; }
相关文章推荐
- telnet发送邮件Base64加密
- 字符串指针变量
- ACM3-1016
- hdu5713 K个联通块[2016百度之星复赛B题]
- 个人冲刺——第六天
- 多线程-NSthread
- 剖析递归求二叉树高
- DNS 配置详解
- java数据结构之单链表
- 第十三周学习进度
- 新手建站需要知道的一些知识
- Chrome 离线版 并 安装报错0x80004002解决
- 求一组数的平均数(利用可变参数列表)
- c++中的顺序表写法,主要实现(增删查改,构造函数,运算符重载)
- c++中的双向链表写法,主要实现(增删查改,链表逆置,构造函数,运算符重载,等)
- 小明哥教你使用模板函数实现顺序表
- [C++] 利用模板的模板参数实现单链表
- 初试-&gt;广义表
- 排序算法之插入排序
- 古典密码之hill密码的加密与解密程序实现