zoukankan      html  css  js  c++  java
  • CF504E. Misha and LCP on Tree(长链剖分求k级祖先)

    题目大意

    题解

    二分+hash判断

    长链剖分求k级祖先

    性质:一个点的k级祖先所在链长度>=k

    证明:如果该点和祖先在同一条链上则得证,否则存在更长的链

    在每条链顶维护往上/下len个,找的时候先跳到2i级祖先(2i<k且i最大),然后O(1)找即可

    因为2^i级祖先所在链长度>=2^i,且k-2^i<2^i,所以可以找到

    code

    卡nmb常

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define min(a,b) (a<b?a:b)
    #define mod 1000000007
    #define Mod 1000000005
    #define ll long long
    //#define file
    using namespace std;
    
    int a[600001][2],ls[300001],fa[300001][19],d[300001],nx[300001],f[300001],Len[300001],top[300001];
    int bg1[300001],ed1[300001],b1[300001],bg2[300001],ed2[300001],b2[300001],mx[300001],p2[19];
    ll p[300002],P[300002],hs1[300001],hs2[300001],np;
    int Q,n,i,j,k,l,len,X1,Y1,X2,Y2,L,R,Mid,Lca1,Lca2;
    char st[300001],ch,St[21];
    
    ll qpower(ll a,int b) {ll ans=1; while (b) {if (b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;} return ans;}
    void New(int x,int y) {++len;a[len][0]=y;a[len][1]=ls[x];ls[x]=len;}
    void Read(int &x) {x=0; ch=getchar(); while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();}
    void Write(int x) {if (!x) {putchar('0');putchar('
    ');return;}int i=0; while (x) St[++i]=x%10+'0',x/=10; while (i) putchar(St[i--]);putchar('
    ');}
    
    void swap(int &x,int &y) {int z=x;x=y;y=z;}
    int lca(int x,int y)
    {
    	int i;
    	if (d[x]<d[y]) swap(x,y);
    	fd(i,18,0) if (d[fa[x][i]]>=d[y]) x=fa[x][i];
    	fd(i,18,0) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    	if (x!=y) x=fa[x][0];
    	return x;
    }
    
    void dfs(int Fa,int t)
    {
    	int i;
    	fa[t][0]=Fa;
    	d[t]=d[Fa]+1;
    	fo(i,1,18) fa[t][i]=fa[fa[t][i-1]][i-1];
    	hs1[t]=(hs1[Fa]*27+(st[t]-'a'+1))%mod;
    	hs2[t]=(hs2[Fa]+p[d[t]]*(st[t]-'a'+1))%mod;
    	
    	for (i=ls[t]; i; i=a[i][1])
    	if (a[i][0]!=Fa)
    	{
    		dfs(t,a[i][0]);
    		if (f[a[i][0]]+1>f[t])
    		f[t]=f[a[i][0]]+1,nx[t]=a[i][0];
    	}
    }
    ll get1(int x,int y) {return hs1[y]-hs1[fa[x][0]]*p[d[y]-d[x]+1];}
    ll get2(int x,int y) {return (hs2[y]-hs2[x])*P[d[x]+1];}
    
    void Dfs(int Fa,int t)
    {
    	int i;
    	if (nx[t])
    	{
    		Len[nx[t]]=Len[t]+1,top[nx[t]]=top[t];
    		Dfs(t,nx[t]);
    	}
    	
    	for (i=ls[t]; i; i=a[i][1])
    	if (a[i][0]!=Fa && a[i][0]!=nx[t])
    	top[a[i][0]]=a[i][0],Len[a[i][0]]=0,Dfs(t,a[i][0]);
    	
    	if (nx[Fa]==t) Len[Fa]=Len[t];
    }
    void Init()
    {
    	np=qpower(27,Mod);
    	p[0]=P[0]=1;
    	fo(i,1,n+1) p[i]=p[i-1]*27%mod,P[i]=P[i-1]*np%mod;
    }
    void init()
    {
    	top[1]=1,Dfs(0,1);
    	l=0;
    	fo(i,1,n)
    	if (nx[fa[i][0]]!=i)
    	{
    		bg1[i]=l+1,k=i;
    		fo(j,0,Len[i])
    		{
    			++l;
    			b1[l]=k,k=fa[k][0];
    			if (!k) break;
    		}
    		ed1[i]=l;
    	}
    	l=0;
    	fo(i,1,n)
    	if (nx[fa[i][0]]!=i)
    	{
    		bg2[i]=l+1,k=i;
    		fo(j,0,Len[i])
    		++l,b2[l]=k,k=nx[k];
    		ed2[i]=l;
    	}
    	fo(i,1,n) mx[i]=floor(log2(i));
    	p2[0]=1;fo(i,1,18) p2[i]=p2[i-1]*2;
    }
    
    int jump(int t,int s)
    {
    	int i,j,k,l;
    	if (!s) return t;
    	
    	t=fa[t][mx[s]],s-=p2[mx[s]];
    	if (d[t]-d[top[t]]<s)
    	return b1[bg1[top[t]]+s-(d[t]-d[top[t]])];
    	else
    	return b2[bg2[top[t]]+(d[t]-d[top[t]])-s];
    }
    
    ll get(int x,int y,int lca,int s)
    {
    	int i,j,k,l;
    	ll s1,s2;
    	if (lca==x)
    	{
    		k=jump(y,(d[y]-d[x]+1)-s);
    		return get2(fa[x][0],k);
    	}
    	else
    	if (lca==y)
    	{
    		k=jump(x,s-1);
    		return get1(k,x);
    	}
    	else
    	{
    		if (s<=d[x]-d[lca]+1)
    		{k=jump(x,s-1);return get1(k,x);}
    		else
    		{s1=get1(lca,x),k=jump(y,(d[x]+d[y]-2*d[lca]+1)-s),s2=get2(lca,k)%mod;return s1+s2*p[d[x]-d[lca]+1];}
    	}
    }
    
    int main()
    {
    	#ifdef file
    	freopen("CF504E.in","r",stdin);
    	freopen("a.out","w",stdout);
    	#endif
    	
    	Read(n);
    	scanf("%s",st+1);
    	fo(i,1,n-1) Read(j),Read(k),New(j,k),New(k,j);
    	Init();
    	dfs(0,1);
    	init();
    	
    	Read(Q);
    	for (;Q;--Q)
    	{
    		Read(X1),Read(Y1),Read(X2),Read(Y2);
    		Lca1=lca(X1,Y1),Lca2=lca(X2,Y2);
    		L=1,R=min(d[X1]+d[Y1]-d[Lca1]*2,d[X2]+d[Y2]-d[Lca2]*2)+1;
    		while (L<R)
    		{
    			Mid=(L+R)/2;
    			if (!((get(X1,Y1,Lca1,Mid)-get(X2,Y2,Lca2,Mid))%mod))
    			L=Mid+1; else R=Mid;
    		}
    		L-=(get(X1,Y1,Lca1,L)-get(X2,Y2,Lca2,L))%mod!=0;
    		Write(L);
    	}
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    期末总结
    作业01 第一次作业 入门
    C语言I博客作业09
    C语言I博客作业08
    C语言I博客作业07
    C语言I博客作业06
    C语言|博客作业05
    通过Excel批量导入数据-Java代码
    python3-easygui模块安装
    com.alibaba.fastjson.JSONArray cannot be cast to XX
  • 原文地址:https://www.cnblogs.com/gmh77/p/13676178.html
Copyright © 2011-2022 走看看