标签:oid 查询 保存 统计 一个 trap str -- getc
题意:给你一棵节点带权树。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)。
标签:oid 查询 保存 统计 一个 trap str -- getc
原文地址:https://www.cnblogs.com/Scx117/p/9110402.html