思路就是二分找到路径上第一个有用的可并点,然后树剖用BIT维护哈希值再启发式合并,但好像哈希的某个地方挂了
#include <bits/stdc++.h>
#define il inline
using namespace std;
typedef unsigned long long ll;
const ll mod=1e9+7,mul=19260817;
il ll qp(ll a,ll b){
ll ans=1ll;
while(b){
if(b&1) ans=(ans*a)%mod;
a=(a*a)%mod,b>>=1;
}
return ans;
}
il void addd(ll &x,ll y){x=(x+y>=mod?x+y-mod:x+y);}
il ll add(ll x,ll y){return (x+y>=mod)?x+y-mod:x+y;}
il ll del(ll x,ll y){return (x<y?x-y+mod:x-y);}
const int N=2e5+5;
int n,m,fa[N],de[N],siz[N],dfn[N],id[N],top[N],son[N],cnt;
int l[N],r[N],f[N],cl[N],cr[N],ff[N][20];
ll ans=1ll,pw[N],inv[N];
struct node{
ll tree[N],val[N];
il node(){memset(tree,0,sizeof(tree));memset(val,0,sizeof(val));}
il void add(int x,ll v){while(x<=n) addd(tree[x],v),x+=(x&-x);}
il void ad(int x,ll v){add(dfn[x],del(v,val[x])),add(dfn[x]+siz[x],del(val[x],v)),val[x]=v;}
il ll get(int x){ll ret=0ll;while(x) ret+=tree[x],x-=(x&-x);return ret%mod;}
il ll gt(int x,int y){return del(get(x),get(fa[y]));}
}A,B;
vector<int> s[N];
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
il void Union(int x,int y){
x=find(x),y=find(y);
if(x==y) return ;
if(s[x].size()<s[y].size()) swap(x,y);
f[y]=x;
for(int it:s[y]) s[x].push_back(it),A.ad(it,(x*pw[de[it]])%mod),B.ad(it,(x*inv[de[it]])%mod);
ans=(ans*qp(cr[x]-cl[x]+1ll,mod-2ll))%mod;
ans=(ans*qp(cr[y]-cl[y]+1ll,mod-2ll))%mod;
cl[x]=max(cl[x],cl[y]),cr[x]=min(cr[x],cr[y]);
if(cl[x]>cr[x]) ans=0ll;
else ans=(ans*(cr[x]-cl[x]+1ll))%mod;
}
vector<int> e[N];
il void add(int x,int y){e[x].push_back(y);}
void dfs1(int x){
de[x]=de[fa[x]]+1,siz[x]=1,ff[x][0]=fa[x];
for(int i=1;i<=18;++i) ff[x][i]=ff[ff[x][i-1]][i-1];
for(int y:e[x]){
dfs1(y),siz[x]+=siz[y];
if(siz[y]>siz[son[x]]) son[x]=y;
}
}
void dfs2(int x,int t){
dfn[++cnt]=x,top[x]=t;
if(son[x]) dfs2(son[x],t);
for(int y:e[x]) if(y!=son[x]) dfs2(y,y);
}
il int lca(int x,int y){
while(top[x]!=top[y]){
if(de[top[x]]<de[top[y]]) swap(x,y);
x=fa[top[x]];
}
return de[x]<de[y]?x:y;
}
il int jump(int x,int k){
for(int i=18;i>=0;--i) if(ff[x][i] && de[x]-de[ff[x][i]]<k) k-=de[x]-de[ff[x][i]],x=ff[x][i];
return x;
}
il int getkth(int x,int y,int z,int k){
if(x==z) return jump(y,de[y]-de[z]+1-k+1);
if(k<=de[x]-de[z]+1) return jump(x,k);
else return jump(y,de[x]+de[y]-2*de[z]+1-k+1);
}
il int to(int x,int y){
for(int i=18;i>=0;--i) if(de[ff[x][i]]>de[y]) x=ff[x][i];
return x;
}
il ll get(int x,int y,int z,int k){
if(x==z){int u=jump(y,de[y]-de[z]+1-k+1);return (B.gt(u,x)*pw[de[u]]%mod);}
if(k<=de[x]-de[z]+1){int u=jump(x,k);return (A.gt(x,u)*inv[de[u]])%mod;}
int u=jump(y,de[x]+de[y]-2*de[z]+1-k+1),v=to(x,z);
ll a,b=(B.gt(u,z)*pw[de[u]])%mod;
if(de[x]<=k-1) a=(A.gt(x,v)*pw[k-1-de[x]])%mod;
else a=(A.gt(x,v)*inv[de[x]-k+1])%mod;
return add(a,b);
}
int a,b,c,d,u,v,w,x,y,z,L,R,mid,cur;
int main(){
scanf("%d",&n);pw[0]=1ll;
for(int i=1;i<=n;++i) pw[i]=(pw[i-1]*mul)%mod;
inv[n]=qp(pw[n],mod-2ll);for(int i=n-1;i>=0;--i) inv[i]=(inv[i+1]*mul)%mod;
for(int i=2;i<=n;++i) scanf("%d",&fa[i]),add(fa[i],i);
for(int i=1;i<=n;++i) scanf("%d%d",&l[i],&r[i]),f[i]=i,s[i].push_back(i),cl[i]=l[i],cr[i]=r[i],ans=(ans*(r[i]-l[i]+1ll))%mod;
dfs1(1),dfs2(1,1);
for(int i=1;i<=n;++i) A.ad(i,(f[i]*pw[de[i]])%mod),B.ad(i,(f[i]*inv[de[i]])%mod);
scanf("%d",&m);
while(m--){
scanf("%d%d%d%d",&a,&b,&c,&d);
if(!ans){puts("0");continue;}
u=lca(a,b),v=lca(c,d),w=de[a]+de[b]-2*de[u]+1;
while(get(a,b,u,w)!=get(c,d,v,w)){
L=1,R=w,cur=0;
while(L<=R){
mid=(L+R)>>1;
if(get(a,b,u,mid)!=get(c,d,v,mid)) cur=mid,R=mid-1;
else L=mid+1;
}
//printf("*** %d %d %d %llu\n",a,b,cur,get(a,b,u,cur));
printf("*** %d %d %d %llu\n",a,b,cur,(3ll*mul*mul)%mod);
//printf("*** %d %d %d %llu\n",c,d,cur,get(c,d,v,cur));
Union(getkth(a,b,u,cur),getkth(c,d,v,cur));
}
printf("%llu\n",ans);
}
return 0;
}