字典树
来源:互联网 发布:驾考预约软件 编辑:程序博客网 时间:2024/06/05 10:45
poj 3764 The xor-longest Path
题意:给定一棵树,问你最长的异或路径。
思路:想到
这样对于
相当于给定
#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <string>#include <cstring>#include <map>#include <vector>#include <queue>#include <stack>#include <set>#include <cstdlib>#define ll o<<1#define rr o<<1|1#define CLR(a, b) memset(a, (b), sizeof(a))using namespace std;typedef long long LL;typedef pair<int, int> pii;const int MAXN = 1e5 + 10;const int INF = 1e9 + 10;const double PI = acos(-1.0);const double eps = 1e-6;const int MOD = 1e9 + 7;void add(LL &x, LL y) { x += y; x %= MOD; }struct Edge { int from, to, val, next;};Edge edge[MAXN * 2];int head[MAXN], edgenum;void addEdge(int u, int v, int w) { Edge E = {u, v, w, head[u]}; edge[edgenum] = E; head[u] = edgenum++;}int Next[31 * MAXN][2], word[31 * MAXN], L, root;int f[40];int newnode() { Next[L][0] = Next[L][1] = -1; word[L++] = 0; return L - 1;}void init() { L = 0; root = newnode(); }void Insert(int val) { int u = root; for(int i = 30; i >= 0; i--) { int v = (val & f[i]) ? 1 : 0; if(Next[u][v] == -1) { Next[u][v] = newnode(); } u = Next[u][v]; word[u]++; }}int Query(int val) { int ans = 0; int u = root; for(int i = 30; i >= 0; i--) { int v = (val & f[i]) ? 1 : 0; if(v == 0) { if(Next[u][1] != -1 && word[Next[u][1]]) { ans ^= f[i]; u = Next[u][1]; } else { u = Next[u][0]; } } else { if(Next[u][0] != -1 && word[Next[u][0]]) { ans ^= f[i]; u = Next[u][0]; } else { u = Next[u][1]; } } } return ans;}int val[MAXN];void DFS(int u, int fa) { for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(v == fa) continue; val[v] = val[u] ^ edge[i].val; DFS(v, u); }}int main(){ f[0] = 1; for(int i = 1; i <= 30; i++) { f[i] = f[i - 1] * 2; } int n; while(scanf("%d", &n) != EOF) { for(int i = 1; i <= n; i++) head[i] = -1, val[i] = 0; edgenum = 0; for(int i = 1; i <= n - 1; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); u++; v++; addEdge(u, v, w); addEdge(v, u, w); } DFS(1, -1); init(); int ans = 0; for(int i = 2; i <= n; i++) { Insert(val[i]); ans = max(ans, val[i]); } for(int i = 2; i <= n; i++) { ans = max(Query(val[i]), ans); } printf("%d\n", ans); } return 0;}
lightoj 1269 - Consecutive Sum
题意:给你连续子序列的最大异或值和最小异或值。
维护前缀异或和即可。
#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <string>#include <cstring>#include <map>#include <vector>#include <queue>#include <stack>#include <set>#include <cstdlib>#define ll o<<1#define rr o<<1|1#define CLR(a, b) memset(a, (b), sizeof(a))using namespace std;typedef long long LL;typedef pair<int, int> pii;const int MAXN = 5e4 + 10;const int INF = 1e9 + 10;const double PI = acos(-1.0);const double eps = 1e-6;const int MOD = 1e9 + 7;void add(LL &x, LL y) { x += y; x %= MOD; }struct Edge { int from, to, val, next;};Edge edge[MAXN * 2];int head[MAXN], edgenum;void addEdge(int u, int v, int w) { Edge E = {u, v, w, head[u]}; edge[edgenum] = E; head[u] = edgenum++;}int Next[31 * MAXN][2], word[31 * MAXN], L, root;int f[40];int newnode() { Next[L][0] = Next[L][1] = -1; word[L++] = 0; return L - 1;}void init() { L = 0; root = newnode(); }void Insert(int val) { int u = root; for(int i = 30; i >= 0; i--) { int v = (val & f[i]) ? 1 : 0; if(Next[u][v] == -1) { Next[u][v] = newnode(); } u = Next[u][v]; word[u]++; }}int Query_Max(int val) { int u = root; for(int i = 30; i >= 0; i--) { int v = (val & f[i]) ? 1 : 0; if(v == 0) { if(Next[u][1] != -1 && word[Next[u][1]]) { val ^= f[i]; u = Next[u][1]; } else { u = Next[u][0]; } } else { if(Next[u][0] != -1 && word[Next[u][0]]) { u = Next[u][0]; } else { val ^= f[i]; u = Next[u][1]; } } } return val;}int Query_Min(int val) { int u = root; for(int i = 30; i >= 0; i--) { int v = (val & f[i]) ? 1 : 0; if(v == 1) { if(Next[u][1] != -1 && word[Next[u][1]]) { val ^= f[i]; u = Next[u][1]; } else { u = Next[u][0]; } } else { if(Next[u][0] != -1 && word[Next[u][0]]) { u = Next[u][0]; } else { val ^= f[i]; u = Next[u][1]; } } } return val;}int main(){ f[0] = 1; for(int i = 1; i <= 30; i++) { f[i] = f[i - 1] * 2; } int t, kcase = 1; scanf("%d", &t); while(t--) { int n; scanf("%d", &n); init(); int ans1 = 0, ans2 = (int)((1LL << 31) - 1); int sum = 0; for(int i = 1; i <= n; i++) { int v; scanf("%d", &v); sum ^= v; if(i > 1) { ans1 = max(Query_Max(sum), ans1); ans2 = min(Query_Min(sum), ans2); } Insert(sum); ans1 = max(sum, ans1); ans2 = min(sum, ans2); } printf("Case %d: %d %d\n", kcase++, ans1, ans2); } return 0;}
hdoj 5715 XOR 游戏
有毒。。。
字典树节点
思路:考虑二分答案,这样就变成了判定性问题。
对于当前的答案
即有
每次在字典树上插入合法的
那样就是求解异或
#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <string>#include <cstring>#include <map>#include <vector>#include <queue>#include <stack>#include <set>#include <cstdlib>#define ll o<<1#define rr o<<1|1#define CLR(a, b) memset(a, (b), sizeof(a))using namespace std;typedef long long LL;typedef pair<int, int> pii;const int MAXN = 1e4 + 10;const int INF = 1e9 + 10;const double PI = acos(-1.0);const double eps = 1e-6;const int MOD = 1e9 + 7;void add(LL &x, LL y) { x += y; x %= MOD; }int f[31];struct Trie { int Next[31 * MAXN][2], word[31 * MAXN], L, root; int newnode() { Next[L][0] = Next[L][1] = 0; word[L++] = 0; return L - 1; } void init() { L = 0; root = newnode(); } void Insert(int val) { int u = root; for(int i = 30; i >= 0; i--) { int v = (val & f[i]) ? 1 : 0; if(Next[u][v] == 0) { Next[u][v] = newnode(); } u = Next[u][v]; word[u]++; } } void Delete(int val) { int u = root; for(int i = 30; i >= 0; i--) { int v = (val & f[i]) ? 1 : 0; u = Next[u][v]; word[u]--; } } int Query(int val) { int u = root, ans = 0; for(int i = 30; i >= 0; i--) { int v = (val & f[i]) ? 1 : 0; if(Next[u][v ^ 1] != 0 && word[Next[u][v ^ 1]]) { ans ^= f[i]; u = Next[u][v ^ 1]; } else { u = Next[u][v]; } } return ans; }}; Trie trie[11];bool dp[MAXN][11];int sum[MAXN];int N, M, L;bool judge(int o) { for(int i = 0; i <= M; i++) { trie[i].init(); } for(int i = 0; i <= N; i++) { for(int j = 0; j <= M; j++) { dp[i][j] = false; } } trie[0].Insert(sum[0]); dp[0][0] = true; for(int i = 1; i <= N; i++) { for(int j = M; j >= 1; j--) { if(i - L > 0) { if(dp[i - L - 1][j - 1]) { trie[j - 1].Delete(sum[i - L - 1]); } } if(trie[j - 1].Query(sum[i]) >= o) { dp[i][j] = true; trie[j].Insert(sum[i]); } } } return dp[N][M];}int main(){ f[0] = 1; for(int i = 1; i <= 30; i++) { f[i] = f[i - 1] * 2; } int t, kcase = 1; scanf("%d", &t); while(t--) { scanf("%d%d%d", &N, &M, &L); sum[0] = 0; for(int i = 1; i <= N; i++) { int v; scanf("%d", &v); sum[i] = sum[i - 1] ^ v; } int l = 0, r = (1 << 30) - 1; int ans = 0; while(r >= l) { int mid = l + r >> 1; if(judge(mid)) { ans = mid; l = mid + 1; } else { r = mid - 1; } } printf("Case #%d:\n%d\n", kcase++, ans); } return 0;}
几道水题
lightoj 1114 - Easily Readable
lightoj 1129 - Consistency Checker
lightoj 1224 - DNA Prefix
这道题有点意思吧,n个串中选出任意个。问max(串数目 * 公共前缀长度)
就相当于把串扫一遍,统计最小覆盖。中间要加个特判剪枝。
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树。。
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- hdu5787 数位dp
- struts学习遇到问题之一 action
- Codeforces Round #368 (Div. 2) A Brain's Photos(水)
- scrollview 包裹ListView recyclerview 为什么会不显示
- STL算法之移除性算法
- 字典树
- SDUT OJ 3377数据结构实验之查找五:平方之哈希表
- 免费下载电子书攻略
- Opencv Mat矩阵中data、size、depth、elemSize、step等属性的理解
- Comparable接口和Comparator接口的区别
- lightoj 1282 - Leading and Trailing (数学--log使用)
- Codeforces Round #368 (Div. 2) B Bakery(水)
- java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start com
- Windows核心编程 第四章 进程(上)