杭州现场赛的题目,首先求出每个节点到根节点的xor值,那么两个节点路径的xor值就等于他们到根节点的xor值再xor。
那么就会有n*n个xor值,但是题目值要求前面的k个,并且k小于200000.
那么就可以这么搞了,先找xor之后最高位为1的,看看有多少个,如果大于k,那么证明前k大的全部在里面,再找次高位的就可以,否者,把这些数全部找出来并排序,剩下的再在这一位不为一的那里找。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=2e5+9;
int n,m,k;
int head[maxn],lon;
long long d[maxn];
long long a[maxn<<1];
int lona;
int end;
struct
{
int next,to;
long long w;
}e[maxn<<1];
struct
{
long long l1,r1;
long long l2,r2;
}data[2][11111111];
void edgemake(int from,int to,long long w)
{
e[++lon].to=to;
e[lon].w=w;
e[lon].next=head[from];
head[from]=lon;
}
void edgeini()
{
memset(head,-1,sizeof(head));
lon=-1;
}
void dfs(int t,int from)
{
for(int k=head[t];k!=-1;k=e[k].next)
{
int u=e[k].to;
if(u==from) continue;
d[u]=d[t]^e[k].w;
dfs(u,t);
}
}
int get(int l,int r,int x)
{
long long tmp=(long long)1<<x;
for(int i=r;i>=l;i--)
if(d[i]&tmp) return i;
return l-1;
}
long long x[11111111],y[11111111];
void bfs(int tmp,int now)
{
long long sum=0;
for(int i=1;i<=end;i++)
{
x[i]=get(data[now][i].l1,data[now][i].r1,tmp-1);
y[i]=get(data[now][i].l2,data[now][i].r2,tmp-1);
sum+=(x[i]-data[now][i].l1+1)*(data[now][i].r2-y[i]);
sum+=(data[now][i].r1-x[i])*(y[i]-data[now][i].l2+1);
}
// printf("%d %d\n",x[1],y[1]);
// printf("%I64d %I64d\n",data[now][1].l1,data[now][1].r1);
if(sum<=k)
{
k-=sum;
for(int i=1;i<=end;i++)
{
for(int p=data[now][i].l1;p<=x[i];p++)
for(int q=y[i]+1;q<=data[now][i].r2;q++)
a[++lona]=d[p]^d[q];
for(int p=x[i]+1;p<=data[now][i].r1;p++)
for(int q=data[now][i].l2;q<=y[i];q++)
a[++lona]=d[p]^d[q];
}
sort(a+lona-sum+1,a+lona+1,greater<long long>());
int top=end;
end=0;
int to=now^1;
for(int i=top;i>=1;i--)
{
if(x[i]>=data[now][i].l1&&y[i]>=data[now][i].l2)
{
data[to][++end].l1=data[now][i].l1;
data[to][end].r1=x[i];
data[to][end].l2=data[now][i].l2;
data[to][end].r2=y[i];
}
if(x[i]+1<=data[now][i].r1&&y[i]+1<=data[now][i].r2)
{
data[to][++end].l1=x[i]+1;
data[to][end].r1=data[now][i].r1;
data[to][end].l2=y[i]+1;
data[to][end].r2=data[now][i].r2;
}
}
}
else
{
int top=end;
end=0;
int to=now^1;
for(int i=top;i>=1;i--)
{
if(x[i]>=data[now][i].l1&&y[i]+1<=data[now][i].r2)
{
data[to][++end].l1=data[now][i].l1;
data[to][end].r1=x[i];
data[to][end].l2=y[i]+1;
data[to][end].r2=data[now][i].r2;
}
if(x[i]+1<=data[now][i].r1&&y[i]>=data[now][i].l2)
{
data[to][++end].l1=x[i]+1;
data[to][end].r1=data[now][i].r1;
data[to][end].l2=data[now][i].l2;
data[to][end].r2=y[i];
}
}
}
}
void solve()
{
lona=0;
d[1]=0;
dfs(1,-1);
sort(d+1,d+1+n,greater<long long>());
end=1;
data[0][end].l1=1;
data[0][end].r1=n;
data[0][end].l2=1;
data[0][end].r2=n;
for(int i=62;i>=1;i--)
{
bfs(i,i&1);
if(k==0) break;
}
if(k>0)
{
long long tmp=d[data[0][1].l1]^d[data[0][1].l2];
while(k>0)
{
a[++lona]=tmp;
k--;
}
}
}
int qry[maxn];
int main()
{
// freopen("in.txt","r",stdin);
while(scanf("%d",&n),n)
{
edgeini();
for(int i=1,from,to;i<n;i++)
{
long long w;
scanf("%d%d%I64d",&from,&to,&w);
edgemake(from,to,w);
edgemake(to,from,w);
}
scanf("%d",&m);
k=0;
for(int i=1;i<=m;i++)
{
scanf("%d",&qry[i]);
k=max(k,qry[i]);
}
solve();
long long maxm=(long long)n*(n-1);
for(int i=1;i<=m;i++)
{
if(qry[i]<=maxm)
printf("%I64d\n",a[qry[i]]);
else
printf("-1\n");
}
}
return 0;
}