Tsinsen-1486:树【Trie树 + 点分治】
2015-12-04 12:53
190 查看
暴力部分:
这个题一开始的想法是 n^2 枚举两个点,然后logn维护LCA,在倍增的同时维护异或值和 k 的个数。
s_z_l老爷指导了新的思路,既然这个树只有n^2个LCA,那么枚举LCA,同时向下深搜即可。
标算:
首先点分治,尽力保证树的平衡,然后按照Trie树的性质,贪心,至于k,我们可以把每个节点的值置为like值的最大值,然后在走左右儿子的时候判断一下即可。
点分治时 !vis[E[i].v] && E[i].v != fa 一定不要忘
View Code
这个题一开始的想法是 n^2 枚举两个点,然后logn维护LCA,在倍增的同时维护异或值和 k 的个数。
s_z_l老爷指导了新的思路,既然这个树只有n^2个LCA,那么枚举LCA,同时向下深搜即可。
标算:
首先点分治,尽力保证树的平衡,然后按照Trie树的性质,贪心,至于k,我们可以把每个节点的值置为like值的最大值,然后在走左右儿子的时候判断一下即可。
点分治时 !vis[E[i].v] && E[i].v != fa 一定不要忘
#include <bits/stdc++.h> #define rep(i, a, b) for (int i = a; i <= b; i++) #define REP(i, a, b) for (int i = a; i < b; i++) #define drep(i, a, b) for (int i = a; i >= b; i--) #define travel(x) for (int i = G[x]; i; i = E[i].nx) #define mp make_pair #define pb push_back #define clr(x) memset(x, 0, sizeof(x)) #define xx first #define yy second using namespace std; typedef long long i64; typedef pair<int, int> pii; //******************************** const int maxn = 100005; struct Ed { int u, v, nx; Ed() {} Ed(int _u, int _v, int _nx) : u(_u), v(_v), nx(_nx) {} } E[maxn << 1]; int G[maxn], cnt_e; void addedge(int u, int v) { E[++cnt_e] = Ed(u, v, G[u]); G[u] = cnt_e; } int vis[maxn]; pii sta[maxn]; int top; int rt; int f[maxn], size[maxn], sum; void getrt(int x, int fa) { f[x] = 0, size[x] = 1; travel(x) { if (!vis[E[i].v] && E[i].v != fa) { getrt(E[i].v, x); size[x] += size[E[i].v]; f[x] = max(f[x], size[E[i].v]); } } f[x] = max(f[x], sum - size[x]); if (f[x] < f[rt]) rt = x; } int read() { int l = 1, s(0); char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') l = -1; ch = getchar(); } while (ch >= '0'&& ch <= '9') { s = (s << 1) + (s << 3) + ch - '0'; ch = getchar(); } return l * s; } int trie[3000005][2], tab[3000005], rootr; int ntot; int n, K; int c[maxn], w[maxn]; int query(int co, int k) { int ret(0); int p = rootr; if (tab[p] + k < K) return -1; drep(i, 30, 0) { int id = co >> i & 1; if (trie[p][id ^ 1] && tab[trie[p][id ^ 1]] + k >= K) ret |= 1 << i, p = trie[p][id ^ 1]; else if (!trie[p][id] || tab[trie[p][id]] + k < K) { ret = -1; break; } else p = trie[p][id]; } return ret; } void insrt(int co, int k) { int p = rootr; drep(i, 30, 0) { tab[p] = max(tab[p], k); int id = co >> i & 1; if (!trie[p][id]) trie[p][id] = ++ntot; p = trie[p][id]; } tab[p] = max(tab[p], k); } int ans = -1; void dfs_query(int x, int fa, int co, int k) { sta[++top] = mp(co, k); ans = max(ans, query(co, k)); for (int i = G[x]; i; i = E[i].nx) if (!vis[E[i].v] && E[i].v != fa) dfs_query(E[i].v, x, co ^ w[E[i].v], k + c[E[i].v]); } /* void dfs_insrt(int x, int fa, int co, int k) { insrt(rootr, co, k, 30); for (int i = G[x]; i; i = E[i].nx) if (!vis[E[i].v] && E[i].v != fa) dfs_insrt(E[i].v, x, co ^ w[E[i].v], k + c[E[i].v]); } */ void solve(int x) { vis[x] = 1; rep(i, 0, ntot) trie[i][0] = trie[i][1] = 0, tab[i] = 0; rootr = 0; ntot = 0; if (c[x] >= K) ans = max(ans, w[x]); insrt(w[x], c[x]); travel(x) { if (vis[E[i].v]) continue; top = 0; dfs_query(E[i].v, x, w[E[i].v], c[E[i].v]); rep(j, 1, top) { sta[j].xx ^= w[x], sta[j].yy += c[x]; insrt(sta[j].xx, sta[j].yy); } } int tmp = sum; for (int i = G[x]; i; i = E[i].nx) { if (!vis[E[i].v]) { rt = 0; sum = size[E[i].v] > size[x] ? tmp - size[x] : size[E[i].v]; getrt(E[i].v, 0); solve(rt); } } } int main() { n = read(), K = read(); rep(i, 1, n) c[i] = read(); rep(i, 1, n) w[i] = read(); REP(i, 1, n) { int x, y; x = read(), y = read(); addedge(x, y), addedge(y, x); } rt = 0, sum = n, f[0] = n + 1; getrt(1, 0); solve(rt); printf("%d\n", ans); return 0; }
View Code
相关文章推荐
- splay初步
- 开源项目XUtils实现多线程下载
- RF+Jenkins构建持续集成
- [软件人生]关于同行竞业,你需要知道,你需要关注-2实例
- Fitbit仍为可穿戴设备龙头老大 苹果屈居第二
- 微软放弃手机版win10 技术支持时间表曝光
- 杭电ACM1250——Hat's Fibonacci
- Java 导入包正确依旧报错的处理方法
- 2015互联网秋招总结--后台开发岗位
- 使用jad批量反编译.class文件
- android studio 更新 Gradle错误解决方法
- 不通过App Store实现ios应用分发下载安装
- 针对博客的9款免费营销工具
- IIS 访问Json文件
- 杭电ACM1131——Count the trees
- RF接口测试本地环境部署
- UINavigationController的popViewControllerAnimated的控制器移除问题
- 周杰伦晒卖萌打球自拍 满脸胡茬笑得爽朗
- iOS通知的介绍
- 解决下载Android Build-tools 19.1.0失败