您的位置:首页 > 其它

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 一定不要忘

#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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: