杭州现场赛的题目,首先求出每个节点到根节点的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; }