【题目大意】
有一棵树,树上一条简单路径(u,v)的价值定义为这条路径的所有边的异或和。求这些价值的第k大。
【思路】
如果我们统计根到节点u,路径的异或和为a[u],显然,路径(u,v)的价值为a[u]^a[v]。问题变为了从n个数中选两个不同的数,求异或,找第k大。因为k其实不是很大,我们可以考虑将1-max(k)的价值都找出来。用a[]建立tire树,首先枚举路径的左端点,通过tire找到一个右端点,使得其异或值最大。把这些数加入优先队列,显然,这些数中,最大的那个,就是第一大的价值。然后把这个价值删掉,通过原来的左端点,再找一个右端点,使其异或值变成次大,并把这个值加入优先队列。这个时候,队列中最大的元素是第二大的价值。这样一直找下去,就能把所有k都找到。
#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<cctype>
#include<string>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<map>
#include<set>
using namespace std;
#define MP(x,y) make_pair((x),(y))
#define PB(x) push_back(x)
typedef __int64 LL;
//typedef unsigned __int64 ULL;
/* ****************** */
const LL INF = 1LL<<55;
const double INFF = 1e100;
const double eps = 1e-8;
const LL mod = 10000000007LL;
const int NN = 100010;
const int MM = 5000010;
/* ****************** */
const int limit = 59;
struct G
{
int v, next;
LL w;
}E[NN*2];
int p[NN], T;
struct node
{
LL x, x_xor;
int num;
node(LL a = 0,LL b = 0,int c = 0):x(a),x_xor(b),num(c){}
bool operator<(const node &tt)const
{
return x_xor < tt.x_xor;
}
};
LL a[NN];
struct Tire
{
int num;
int ch[2];
void init()
{
num = 0;
memset(ch, -1, sizeof(ch));
}
}tire[NN*60];
struct Q
{
int k, id;
bool operator<(const Q &tt)const
{
return k < tt.k;
}
}q[NN];
LL anss[NN];
void add(int u,int v,LL w)
{
E[T].v = v;
E[T].w = w;
E[T].next = p[u];
p[u] = T++;
}
void dfs(int u,int fa)
{
int i, v;
for(i = p[u]; i + 1; i = E[i].next)
{
v = E[i].v;
if(v == fa)continue;
a[v] = a[u]^E[i].w;
dfs(v, u);
}
}
void tire_insert(LL val,int root,int &tire_cnt)
{
int i, x, p = root;
for(i = limit; i >=0; i --)
{
if(val&(1LL<<i))
x = 1;
else
x = 0;
if(tire[p].ch[x]==-1)
{
tire[p].ch[x] = ++tire_cnt;
tire[tire_cnt].init();
}
p = tire[p].ch[x];
}
tire[p].num ++;
}
LL tire_find_max(LL val,int root,int &num)
{
int i, x, p = root;
LL ans = 0;
for(i = limit; i >= 0; i --)
{
if(val&(1LL<<i))
x = 0;
else
x = 1;
if(tire[p].ch[x]!=-1)
{
ans |= (1LL<<i);
p = tire[p].ch[x];
}
else
{
p = tire[p].ch[x^1];
}
}
num = tire[p].num;
return ans;
}
LL tire_find_lower(LL val,LL x_xor,int root,int &num)
{
int i, x, xx, p = root;
int last = -1;
LL ans = 0;
for(i = limit; i >= 0; i --)
{
if( (val^x_xor)&(1LL<<i) )
x = 1;
else
x = 0;
if( val&(1LL<<i))
xx = 0;
else
xx = 1;
if(tire[p].ch[x^1]!=-1 && x == xx)
last = i;
p = tire[p].ch[x];
}
if(last==-1)return -1;
p = root;
for(i = limit; i >= 0; i--)
{
if(i >= last)
{
if( (val^x_xor)&(1LL<<i) )
x = 1;
else
x = 0;
if(i == last)
x = (x^1);
}
else
{
if(val&(1LL<<i))
x = 0;
else
x = 1;
if(tire[p].ch[x]==-1)
x = (x^1);
}
if( ( val^((LL)x<<i) )&(1LL<<i) )
ans |= (1LL<<i);
p = tire[p].ch[x];
}
num = tire[p].num;
return ans;
}
void solve(int n,int m)
{
int i, j, tire_root, tire_cnt, num;
LL t;
priority_queue<node>my_q;
tire_root = tire_cnt = 0;
tire[tire_root].init();
for(i = 1; i <= n; i ++)
{
tire_insert(a[i], tire_root, tire_cnt);
}
for(i = 1; i <= n; i ++)
{
t = tire_find_max(a[i], tire_root, num);
my_q.push( node(a[i], t, num) );
}
j = 1;
memset(anss, -1, sizeof(anss));
for(i = 1; i <= (LL)n*(n-1) && j <= m ; i ++)
{
node ix = my_q.top();
my_q.pop();
while(j <= m && i==q[j].k)
{
anss[q[j].id] = ix.x_xor;
j ++;
}
if(ix.num > 1)
{
my_q.push( node(ix.x, ix.x_xor, ix.num-1) );
}
else
{
t = tire_find_lower(ix.x, ix.x_xor, tire_root, num);
if(t!=-1)
my_q.push( node(ix.x, t, num) );
}
}
for(i = 1; i <= m; i ++)
printf("%I64d\n", anss[i]);
}
int main()
{
int n, m, u, v, i;
LL t;
while(scanf("%d", &n) != EOF)
{
if(n==0)break;
memset(p, -1, sizeof(p));
T = 0;
for(i = 1; i < n; i ++)
{
scanf("%d%d", &u, &v);
scanf("%I64d", &t);
add(u, v, t);
add(v, u, t);
}
a[1] = 0;
dfs(1,-1);
scanf("%d", &m);
for(i = 1; i <= m; i ++)
{
scanf("%d", &q[i].k);
q[i].id = i;
}
sort(q+1,q+1+m);
solve(n, m);
}
return 0;
}