萌新求助,Gasoline prices这题,本机TLE提交UKE
查看原帖
萌新求助,Gasoline prices这题,本机TLE提交UKE
401215
xieziheng楼主2023/7/28 21:29

思路就是二分找到路径上第一个有用的可并点,然后树剖用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;
}
2023/7/28 21:29
加载中...