Scx117
只一眼,便辽阔了时间。

题意:给你一棵节点带权树。q个询问,每次询问u到v的路径上max(a[i]^dis(i,v))?

保证u是v的祖先,i是u->v路径上的点。n,ai<=5e4。

 

标程:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int read()
 4 {
 5    int x=0,f=1;char ch=getchar();
 6    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
 7    while (ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
 8    return x*f;
 9 }
10 const int N=50005;
11 int cnt,n,q,u,v,a[N],dep[N],head[N],fa[N],sc,son[5000][2],t,c,now,sum,f[N][260],jp[N],ans,base;
12 struct node{int to,next;}num[N*2];
13 void add(int x,int y)
14 {num[++cnt].to=y;num[cnt].next=head[x];head[x]=cnt;}
15 void dfs(int x)
16 {
17     for (int i=head[x];i;i=num[i].next)
18       if (num[i].to!=fa[x]) {
19         dep[num[i].to]=dep[x]+1;
20           fa[num[i].to]=x;
21           dfs(num[i].to);
22       }
23 }
24 int main()
25 {
26     n=read();q=read();
27     for (int i=1;i<=n;i++) a[i]=read();
28     for (int i=1;i<n;i++) u=read(),v=read(),add(u,v),add(v,u);
29     dfs(1);
30     for (int i=1;i<=n;i++)
31       if (dep[i]>=255)
32       {
33          int x=i;sc=0;son[0][0]=son[0][1]=0;
34          for (int j=0;j<256;j++,x=fa[x])//add_Trie
35          {
36            t=a[x]^j;now=0;
37            for (int k=16;k>=0;k--)
38            {
39                c=(t>>k)&1;
40                if (!son[now][c]) son[now][c]=++sc,son[sc][0]=son[sc][1]=0;
41                now=son[now][c];
42             }
43          }
44          for (int j=0;j<256;j++)
45          {
46              t=j<<8;now=sum=0;
47              for (int k=16;k>=0;k--)
48              {
49                  c=(t>>k)&1;
50                  if (son[now][c^1]) now=son[now][c^1],sum+=(1<<k);else now=son[now][c];
51             }
52              f[i][j]=sum;
53          }
54          jp[i]=x;
55     }
56    while (q--)
57    {
58        u=read();v=read();ans=base=0;
59        for (;dep[v]-dep[u]>=255;v=jp[v]) ans=max(ans,f[v][base]),base++;
60        for (base=base*256;v!=fa[u];v=fa[v],base++) ans=max(ans,a[v]^base);
61        printf("%d\n",ans);
62     }
63    return 0;
64 }

 

题解:分块+Trie

异或性质:比如需要异或x,那么^(x&255)^((x>>8)<<8)等价。拆数异或值不变。

对于每个点到根的链,每256个分一个块。

每个点x保存f[x][i]表示从x以上256个点的块中max(a[j]^dis(x,j)^(i<<8))。容易用字典树处理出所有i的最大异或值。

查询的时候按照块跳。统计max(f[v][base]),每次base++。

时间复杂度O(q*256+n*256*logn)。

posted on 2018-05-30 13:30  Scx117  阅读(193)  评论(0编辑  收藏  举报