NC213912. 芭芭拉冲鸭~(续)
描述
输入描述
第一行有一个正整数。
接下来的行,每行输入两个正整数
和
,代表
和
之间有一条无向边相连。
接下来一行有一个长度为的字符串,字符串仅由小写字母构成。第
个字符表示节点
上的字母。
接下来一行是一个正整数,代表询问次数。
接下来的行,每行两个正整数
和
。
(保证输入一定是一棵树)
输出描述
对应每次询问,输出一个正整数,代表回文串的最大长度。
示例1
输入:
5 1 2 1 3 2 4 2 5 abcba 3 4 5 1 2 3 3
输出:
3 1 1
说明:
C++(clang++11) 解法, 执行用时: 126ms, 内存消耗: 18868K, 提交时间: 2020-11-21 16:09:36
#pragma GCC optimize("-Ofast","-funroll-all-loops") #include<bits/stdc++.h> //#define int long long using namespace std; const int N=1e5+10; int n,q,s[N],f[N][20],dep[N]; char str[N]; vector<int> g[N]; void dfs(int x,int fa){ s[x]=s[fa]^(1<<(str[x]-'a')); dep[x]=dep[fa]+1; f[x][0]=fa; for(int i=1;i<=17;i++) f[x][i]=f[f[x][i-1]][i-1]; for(int to:g[x]) if(to!=fa) dfs(to,x); } inline int lca(int x,int y){ if(dep[x]<dep[y]) swap(x,y); for(int i=17;i>=0;i--) if(dep[f[x][i]]>=dep[y]) x=f[x][i]; if(x==y) return x; for(int i=17;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0]; } signed main(){ cin>>n; for(int i=1,a,b;i<n;i++) scanf("%d %d",&a,&b),g[a].push_back(b),g[b].push_back(a); scanf("%s",str+1); dfs(1,0); cin>>q; for(int i=1,x,y,lc,cnt,dis;i<=q;i++){ scanf("%d %d",&x,&y); lc=lca(x,y); cnt=0; dis=dep[x]+dep[y]-2*dep[lc]+1; for(int j=0;j<26;j++){ int k=(s[x]>>j&1)^(s[y]>>j&1); if(str[lc]-'a'==j) k^=1; if(k) cnt++; } if(cnt>1) printf("%d\n",dis-cnt+1); else printf("%d\n",dis); } return 0; }