CF504E Misha and LCP on Tree 题解
简单的hsh,每一次二分匹配,总共\(O(n)\)次询问,每一次二分答案,用哈希\(O(1)\)匹配,总复杂度\(O(n \log_2{n})\),直接暴力就可以写过了。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int base2=131;
const int base1=13331;
const int maxn=6e5+10;
const int inv1=598004655;
const int inv2=526717562;
const int modd1=1000000007;
const int modd2=1000000009;
int pwinv1[maxn],pwinv2[maxn],l,r,lca1,lca2,son[maxn];
int hsh1[maxn],hsh2[maxn],pw1[maxn],pw2[maxn],hs1[maxn],m;
int dep[maxn],hs2[maxn],n,x,y,xx,yy,len,lg[maxn],st[maxn][21];
int top[maxn],cnt,dfn[maxn],ans,lin1,lin2,fa[maxn][21],mxdep[maxn];
vector<int>u[maxn],v[maxn],tu[maxn];
string s;
int getz1(int q,int w){
return (hsh1[w]-hsh1[q]*pw1[dep[w]-dep[q]]%modd1+modd1)%modd1;
}
int getz2(int q,int w){
return (hsh2[w]-hsh2[q]*pw2[dep[w]-dep[q]]%modd2+modd2)%modd2;
}
int getd1(int q,int w){
return (hs1[q]-hs1[fa[w][0]]+modd1)*pwinv1[dep[fa[w][0]]]%modd1;
}
int getd2(int q,int w){
return (hs2[q]-hs2[fa[w][0]]+modd2)*pwinv2[dep[fa[w][0]]]%modd2;
}
int lca(int q,int w){
q=dfn[q],w=dfn[w];
if(q>w){
swap(q,w);
}
int ll=lg[w-q+1];
if(dep[st[q][ll]]<dep[st[w-(1<<ll)+1][ll]]){
return st[q][ll];
}
else{
return st[w-(1<<ll)+1][ll];
}
}
pair<int,int> geths(int q,int w){
int qw=lca(q,w);
if(qw==w){
return make_pair(getd1(q,w),getd2(q,w));
}
else if(qw==q){
return make_pair(getz1(fa[q][0],w),getz2(fa[q][0],w));
}
return make_pair((getd1(q,qw)*pw1[dep[w]-dep[qw]]+getz1(qw,w))%modd1,(getd2(q,qw)*pw2[dep[w]-dep[qw]]+getz2(qw,w))%modd2);
}
void dfs(int q,int w){
cnt++;
dfn[q]=cnt;
st[cnt][0]=q;
fa[q][0]=w;
for(int i=1;i<=20;i++){
fa[q][i]=fa[fa[q][i-1]][i-1];
}
dep[q]=dep[w]+1;
hsh1[q]=(hsh1[w]*base1+s[q-1]-'a')%modd1;
hsh2[q]=(hsh2[w]*base2+s[q-1]-'a')%modd2;
hs1[q]=((s[q-1]-'a')*pw1[dep[q]-1]+hs1[w])%modd1;
hs2[q]=((s[q-1]-'a')*pw2[dep[q]-1]+hs2[w])%modd2;
mxdep[q]=dep[q];
for(int i=0;i<tu[q].size();i++){
if(tu[q][i]!=w){
dfs(tu[q][i],q);
cnt++;
st[cnt][0]=q;
if(mxdep[tu[q][i]]>mxdep[son[q]]){
son[q]=tu[q][i];
mxdep[q]=mxdep[tu[q][i]];
}
}
}
return;
}
void dfs1(int q,int w){
top[q]=w;
if(q==w){
for(int i=0,now=q;i<=mxdep[q]-dep[q];i++){
u[q].push_back(now);
now=fa[now][0];
}
for(int i=0,now=q;i<=mxdep[q]-dep[q];i++){
v[q].push_back(now);
now=son[now];
}
}
if(son[q]){
dfs1(son[q],w);
}
for(int i=0;i<tu[q].size();i++){
if(tu[q][i]!=fa[q][0]&&tu[q][i]!=son[q]){
dfs1(tu[q][i],tu[q][i]);
}
}
return;
}
int get_fa(int q,int w){
if(!w){
return q;
}
q=fa[q][lg[w]];
w=w-(1<<lg[w]);
w=w-(dep[q]-dep[top[q]]);
q=top[q];
if(w>=0){
return u[q][w];
}
else{
return v[q][-w];
}
}
int find(int q,int w,int qw,int wq){
if(dep[q]-dep[w]+1>=wq){
return get_fa(q,wq-1);
}
else{
return get_fa(qw,dep[q]+dep[qw]-2*dep[w]+1-wq);
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
pw1[0]=pw2[0]=pwinv1[0]=pwinv2[0]=1;
for(int i=1;i<=3e5;i++){
pw1[i]=pw1[i-1]*base1%modd1;
pw2[i]=pw2[i-1]*base2%modd2;
pwinv1[i]=pwinv1[i-1]*inv1%modd1;
pwinv2[i]=pwinv2[i-1]*inv2%modd2;
}
cin>>n>>s;
for(int i=1;i<n;i++){
cin>>x>>y;
tu[x].push_back(y);
tu[y].push_back(x);
}
dfs(1,0);
dfs1(1,1);
for(int i=2;i<=(n<<1);i++){
lg[i]=lg[i>>1]+1;
}
for(int i=1;i<=20;i++){
for(int j=1;j<=cnt-(1<<i)+1;j++){
if(dep[st[j][i-1]]<dep[st[j+(1<<(i-1))][i-1]]){
st[j][i]=st[j][i-1];
}
else{
st[j][i]=st[j+(1<<(i-1))][i-1];
}
}
}
cin>>m;
while(m--){
cin>>x>>y>>xx>>yy;
l=1;
lca1=lca(x,y);
lca2=lca(xx,yy);
r=min(dep[x]+dep[y]-2*dep[lca1]+1,dep[xx]+dep[yy]-2*dep[lca2]+1);
ans=0;
while(l<=r){
int mid=(l+r)/2;
lin1=find(x,lca1,y,mid);
lin2=find(xx,lca2,yy,mid);
if(geths(x,lin1)==geths(xx,lin2)){
l=mid+1;
ans=mid;
}
else{
r=mid-1;
}
}
cout<<ans<<'\n';
}
return 0;
}
浙公网安备 33010602011771号