省选膜你33

记不太清了,是昨天的模拟赛,昨晚很晚很晚才改完题啊

最近有点消极怠工,今天好不容易才把最后一题改过去......

开场看的第一题,观察出来好多性质,但是无法用线段树维护,所以就完蛋了

第二题吧,看了一会发现ntt可以优化第一步卷积,第二步是乘法,不会了

第三题只写了暴力,还没调对

T1 传教

就是给你一个序列,要把这个序列异或成0序列

于是我们可以先用差分求出来初始的时候每一个长度为k的段需要异或多少,将这个值记录在每一段的第一个位置

这样我们每次只需要统计这样的值不为零的个数就好了,无解的情况就是最后k-1个数有值,因为块长使得最后是不能有数的

开始考虑怎样动态维护这个东东,发现每次修改的是x,x+1的所有同余后缀,将这些数异或上更改的值

那么我们就有了一个\(k>=\sqrt{n}\)的做法,每次暴力往后跳并更新答案,这样复杂度是\(\mathcal{O(n\sqrt{n})}\)

我们开始考虑\(k<=\sqrt{n}\)怎么办,之前都是暴力的,然而这次闷头乱撞了,啥也不是

于是我们分块维护桶,每次就是\(\sqrt{n}\),注意这里我们是对于每个同余分开考虑,但是块长仍位\(\sqrt{n}\),这样可以保证复杂度

AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=2e5+5;
int n,k,q,sq,a[N],b[N],c[N];
int cf[N],an[N],ans,sum;
void print(){
    if(sum)printf("-1\n");
    else printf("%d\n",ans);
}
void spj(){
    fo(i,1,n)if(c[i])ans++;
    print();
    while(q--){
        char ch[5];scanf("%s",ch+1);
        int x=read(),y=read();
        if(ch[1]=='a')y^=a[x];
        if(ch[1]=='b')y^=b[x];
        if(c[x]==y)ans--;
        if(!c[x])ans++;
        print();
        if(ch[1]=='a')a[x]^=y;
        if(ch[1]=='b')b[x]^=y;
        c[x]^=y;
        // fo(i,1,n)cerr<<a[i]<<" ";cerr<<endl;
    }
}
void spj2(){
    print();
    while(q--){
        char ch[5];scanf("%s",ch+1);
        int x=read(),y=read();
        if(ch[1]=='a')y^=a[x];
        if(ch[1]=='b')y^=b[x];
        for(int i=x;i<=n;i+=k){
            if(an[i]==y){
                ans--;
                if(i+k-1>n)sum--;
            }
            if(!an[i]){
                ans++;
                if(i+k-1>n)sum++;
            }
            an[i]^=y;
        }
        for(int i=x+1;i<=n;i+=k){
            if(an[i]==y){
                ans--;
                if(i+k-1>n)sum--;
            }
            if(!an[i]){
                ans++;
                if(i+k-1>n)sum++;
            }
            an[i]^=y;
        }
        print();
        if(ch[1]=='a')a[x]^=y;
        if(ch[1]=='b')b[x]^=y;
        c[x]^=y;
    }
}
vector<int> vec[455];
vector<int> buc[455][455];
int tag[455][455],sm[455],bl[N],la[N],ra[N];
void change(int x,int p,int y){
    p=(p-x)/k;
    // cerr<<"change "<<x<<" "<<p<<" "<<y<<" "<<bl[p]<<" "<<sm[x]<<endl;
    if(bl[p]<=sm[x]){
        fo(i,la[bl[p]],ra[bl[p]]){
            buc[x][bl[p]][vec[x][i]]--;
            vec[x][i]^=tag[x][bl[p]];
            buc[x][bl[p]][vec[x][i]]++;
        }
        tag[x][bl[p]]=0;
        fo(i,p,ra[bl[p]]){
            buc[x][bl[p]][vec[x][i]]--;
            if(vec[x][i]==0)ans++;
            if(vec[x][i]==y)ans--;
            vec[x][i]^=y;
            buc[x][bl[p]][vec[x][i]]++;
        }
    }
    fo(i,bl[p]+1,sm[x]){
        ans+=buc[x][i][tag[x][i]];
        if(ra[i]==(int)vec[x].size()-1){
            if(vec[x][ra[i]]^tag[x][i]==0)sum++;
            if(vec[x][ra[i]]^tag[x][i]==y)sum--;
        }
        tag[x][i]^=y;
        ans-=buc[x][i][tag[x][i]];
    }
    fo(i,max(sm[x]*sq+sq,p),(int)vec[x].size()-1){
        if(vec[x][i]==0){
            ans++;
            if(i+1==vec[x].size()&&x!=n%k+1)sum++;
        }
        if(vec[x][i]==y){
            ans--;
            if(i+1==vec[x].size()&&x!=n%k+1)sum--;
        }
        vec[x][i]^=y;
    }
}
signed main(){
    freopen("mission.in","r",stdin);
    freopen("mission.out","w",stdout);
    n=read();k=read();q=read();sq=sqrt(n);
    fo(i,1,n)a[i]=read();
    fo(i,1,n)b[i]=read();
    fo(i,1,n)c[i]=a[i]^b[i];
    if(k==1)return spj(),0;
    fo(i,1,n){
        cf[i]^=cf[i-1];
        an[i]=c[i]^cf[i];
        cf[i]^=an[i];
        cf[i+k]^=an[i];
        if(i+k-1>n&&an[i])sum++;
        if(an[i])ans++;
    }
    if(k>=sq)return spj2(),0;
    fo(i,0,n)bl[i]=i/sq;
    fo(i,0,n)la[i]=i*sq,ra[i]=i*sq+sq-1;
    fo(i,1,k){sm[i]=-1;
        for(int j=i;j<=n;j+=k)vec[i].push_back(an[j]);
        fo(j,0,n){
            if(j*sq+sq-1>=vec[i].size())continue;
            buc[i][j].resize(1<<15);sm[i]=j;
            fo(k,j*sq,j*sq+sq-1)buc[i][j][vec[i][k]]++;
        }
        // cerr<<sm[i]<<endl;
    }
    // fo(i,1,n)cerr<<an[i]<<" ";cerr<<endl;
    // cerr<<ans<<" "<<sum<<endl;
    print();
    while(q--){
        char ch[5];scanf("%s",ch+1);
        int x=read(),y=read();
        if(ch[1]=='a')y^=a[x];
        if(ch[1]=='b')y^=b[x];
        change((x-1)%k+1,x,y);
        change(x%k+1,x+1,y);
        // fo(i,1,n)cout<<(vec[(i-1)%k+1][(i-1)/k])<<" ";cerr<<endl;
        // cerr<<ans<<" ";
        print();
        if(ch[1]=='a')a[x]^=y;
        if(ch[1]=='b')b[x]^=y;
        c[x]^=y;
    }
    return 0;
}

T2 方程

考场上维护了a+b,乘法不会了,原根就行了

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=1<<20;
const int mod=998244353;
int ksm(int x,int y,int mo=mod){
    int ret=1;
    while(y){
        if(y&1)ret=ret*x%mo;
        x=x*x%mo;y>>=1;
    }return ret;
}
int af[N],w[N],lim,len;
void ntt(int *a,int lim){
    fo(i,0,lim-1)if(af[i]>i)swap(a[i],a[af[i]]);
    for(int t=lim>>1,d=1;d<lim;d<<=1,t>>=1)
        for(int i=0;i<lim;i+=(d<<1))
            fo(j,0,d-1){
                int tmp=a[i+j+d]*w[t*j]%mod;
                a[i+j+d]=(a[i+j]-tmp+mod)%mod;
                a[i+j]=(a[i+j]+tmp)%mod;
            }
}
int p,g,n,m,ans;
int a[N],b[N],c[N];
void mul(int *x,int *y,int *z,int mo=p){
    fo(i,0,p-1)a[i]=x[i],b[i]=y[i];
    for(lim=1,len=0;lim<2*p;lim<<=1,len++);
    fo(i,0,lim-1)af[i]=(af[i>>1]>>1)|((i&1)<<(len-1));
    w[0]=1;w[1]=ksm(3,(mod-1)/lim);
    fo(i,2,lim-1)w[i]=w[i-1]*w[1]%mod;
    ntt(a,lim);ntt(b,lim);
    w[0]=1;w[1]=ksm(w[1],mod-2);
    fo(i,2,lim-1)w[i]=w[i-1]*w[1]%mod;
    fo(i,0,lim-1)c[i]=a[i]*b[i]%mod;
    ntt(c,lim);int iv=ksm(lim,mod-2);
    fo(i,0,lim-1)z[i]=0;
    fo(i,0,lim-1)z[i%mo]=(z[i%mo]+c[i]*iv)%mod,a[i]=b[i]=c[i]=0;
}
int pr[N],cnt,phi[N],mn[N];bool vis[N];
void init(){
    fo(i,2,200000){
        if(!vis[i])pr[++cnt]=i,phi[i]=i-1,mn[i]=cnt;
        for(int j=1;j<=cnt&&i*pr[j]<=200000;j++){
            vis[i*pr[j]]=true;
            if(i%pr[j]==0){phi[i*pr[j]]=phi[i]*pr[j];mn[i*pr[j]]=j;break;}
            else phi[i*pr[j]]=phi[i]*(pr[j]-1),mn[i*pr[j]]=j;
        }
    }
}
int ji[N],cj;
void prime(int x){cj=0;
    while(x!=1){
        if(mn[x]==ji[cj]){x/=pr[mn[x]];continue;}
        ji[++cj]=mn[x];x/=pr[mn[x]];
    }
}
bool jud(int x){
    prime(phi[p]);
    if(ksm(x,phi[p],p)!=1)return false;
    fo(i,1,cj)if(ksm(x,phi[p]/pr[ji[i]],p)==1)return false;
    return true;
}
int findrt(){fo(i,1,p)if(jud(i))return i;}
int ta[N],tb[N],ab[N],tc[N],ia[N],ic[N],pc[N],ys[N];
signed main(){
    freopen("equation.in","r",stdin);
    freopen("equation.out","w",stdout);
    p=read();n=read();m=read();
    fo(i,1,n)ta[read()]=1;
    fo(i,1,m)tb[(read()+1)%p]=true;
    mul(ta,ta,ab);init();g=findrt();
    // fo(i,0,p-1)cerr<<ab[i]<<" ";cerr<<endl;
    int now=1;fo(i,0,p-2)ys[now]=i,now=now*g%p;
    fo(i,1,p-1)ia[ys[ksm(i,p-2,p)]]+=ab[i];
    fo(i,0,p-2)ia[i]%=mod;//cerr<<ia[i]<<" ";cerr<<endl;
    fo(i,1,p-1)tc[ys[i]]+=ta[i];
    fo(i,0,p-2)tc[i]%=mod;//cerr<<tc[i]<<" ";cerr<<endl;
    mul(ia,tc,ic,p-1);
    fo(i,0,p-2)pc[ksm(g,i,p)]+=ic[i];
    fo(i,0,p-1){
        int iv=ksm(i,p-2,p),now=(p-(i+iv*iv)%p)%p;
        if(!tb[now])continue;
        ans=(ans+pc[i])%mod;
    }
    printf("%lld",ans);
}

T3 移花接木

挺复杂的题,看题解+问同学,搞了好久呢

主要是用递归,这递归的题难起来也是啥也不会啊,还要构造函数

发现就是要求每个点到距离他最大深度的点的距离和

我们维护每个树的直径,然后我们需要求距离操作,而这个可以递归求,有用的点只有端点和直径端点

然后构造函数,按着题解上说的干就行了,大致是构造一个距离和函数,仍然递归去做

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=155;
const int mod=998244353;
int ksm(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=ret*x%mod;
        x=x*x%mod;y>>=1;
    }return ret;
}
int m;struct TREE{int n,ta,tb,x,y,s0,s1;}tr[N];
struct DM{
    int id,x,y;DM(){}DM(int a,int b,int c){id=a;x=b;y=c;}
    bool operator < (DM a)const{
        if(id!=a.id)return id<a.id;
        if(x!=a.x)return x<a.x;
        return y<a.y;
    }
};map<DM,int> dm;
int D(int id,int x,int y){
    if(id==0||x==y)return 0;if(x>y)swap(x,y);
    if(dm.find(DM(id,x,y))!=dm.end())return dm[DM(id,x,y)];int ret;
    if(y<=tr[tr[id].ta].n)ret=D(tr[id].ta,x,y);
    else if(x<=tr[tr[id].ta].n&&y>tr[tr[id].ta].n)ret=D(tr[id].ta,x,tr[id].x)+D(tr[id].tb,tr[id].y,y-tr[tr[id].ta].n)+1;
    else if(x>tr[tr[id].ta].n)ret=D(tr[id].tb,x-tr[tr[id].ta].n,y-tr[tr[id].ta].n);
    return dm[DM(id,x,y)]=ret;
}
struct FM{
    int id,s,t,d;FM(){}FM(int a,int b,int c,int e){id=a;s=b;t=c;d=e;}
    bool operator < (FM a)const{
        if(id!=a.id)return id<a.id;
        if(s!=a.s)return s<a.s;
        if(t!=a.t)return t<a.t;
        return d<a.d;
    }
};map<FM,int> fm;
int F(int id,int s,int t,int d){
    if(id==0)return 0;
    if(fm.find(FM(id,s,t,d))!=fm.end())return fm[FM(id,s,t,d)];
    int ret,u=tr[id].x,v=tr[id].y+tr[tr[id].ta].n,ta=tr[id].ta,tb=tr[id].tb;
    if(D(id,s,u)<D(id,s,v)){
        int dst=D(id,s,t),dsu=D(id,s,u),dtu=D(id,t,u);
        if(dst+dtu==dsu&&t<=tr[ta].n)ret=(F(ta,s,t,d)+((dsu+1-d)%mod)*(tr[tb].n%mod)%mod+F(tb,v-tr[ta].n,v-tr[ta].n,0))%mod;
        else if(dsu+dst==dtu&&t<=tr[ta].n&&d)ret=F(ta,s,t,d);
        else if(dsu+dtu==dst&&t>tr[ta].n){
            if(d<=dsu)ret=(F(ta,s,u,d)+((dsu+1-d)%mod)*(tr[tb].n%mod)%mod+F(tb,v-tr[ta].n,t-tr[ta].n,0))%mod;
            else ret=F(tb,v-tr[ta].n,t-tr[ta].n,d-dsu-1);
        }else if(t<=tr[ta].n){int al=(dsu+dst+dtu)/2;
            if(d+dtu<=al)ret=(F(ta,s,t,d)+((dsu+1-d)%mod)*(tr[tb].n%mod)%mod+F(tb,v-tr[ta].n,v-tr[ta].n,0))%mod;
            else ret=F(ta,s,t,d);
        }
    }else {
        int dst=D(id,s,t),dsv=D(id,s,v),dtv=D(id,t,v);
        if(dst+dtv==dsv&&t>tr[ta].n)ret=(F(tb,s-tr[ta].n,t-tr[ta].n,d)+((dsv+1-d)%mod)*(tr[ta].n%mod)%mod+F(ta,u,u,0))%mod;
        else if(dsv+dst==dtv&&t>tr[ta].n&&d)ret=F(tb,s-tr[ta].n,t-tr[ta].n,d);
        else if(dsv+dtv==dst&&t<=tr[ta].n){
            if(d<=dsv)ret=(F(tb,s-tr[ta].n,v-tr[ta].n,d)+((dsv+1-d)%mod)*(tr[ta].n%mod)%mod+F(ta,u,t,0))%mod;
            else ret=F(ta,u,t,d-dsv-1);
        }else if(t>tr[ta].n){
            int al=(dsv+dst+dtv)/2;
            if(d+dtv<=al)ret=(F(tb,s-tr[ta].n,t-tr[ta].n,d)+((dsv+1-d)%mod)*(tr[ta].n%mod)%mod+F(ta,u,u,0))%mod;
            else ret=F(tb,s-tr[ta].n,t-tr[ta].n,d);
        }
    }return fm[FM(id,s,t,d)]=ret%mod;
}
struct GM{
    int id,s,t,d;GM(){}GM(int a,int b,int c,int e){id=a;s=b;t=c;d=e;}
    bool operator < (GM a)const{
        if(id!=a.id)return id<a.id;
        if(s!=a.s)return s<a.s;
        if(t!=a.t)return t<a.t;
        return d<a.d;
    }
};
map<GM,int> gm;
int G(int id,int s,int t,int d){
    if(id==0)return 1;if(gm.find(GM(id,s,t,d))!=gm.end())return gm[GM(id,s,t,d)];
    int ret,u=tr[id].x,v=tr[id].y+tr[tr[id].ta].n,ta=tr[id].ta,tb=tr[id].tb;
    if(D(id,s,u)<D(id,s,v)){
        int dst=D(id,s,t),dsu=D(id,s,u),dtu=D(id,t,u);
        if(dst+dtu==dsu&&t<=tr[ta].n)ret=(G(ta,s,t,d)+G(tb,v-tr[ta].n,v-tr[ta].n,0))%mod;
        else if(dsu+dst==dtu&&t<=tr[ta].n&&d)ret=G(ta,s,t,d);
        else if(dsu+dtu==dst&&t>tr[ta].n){
            if(d<=dsu)ret=(G(ta,s,u,d)+G(tb,v-tr[ta].n,t-tr[ta].n,0))%mod;
            else ret=G(tb,v-tr[ta].n,t-tr[ta].n,d-dsu-1);
        }else if(t<=tr[ta].n){
            int al=(dsu+dst+dtu)/2;
            if(d+dtu<=al)ret=(G(ta,s,t,d)+G(tb,v-tr[ta].n,v-tr[ta].n,0))%mod;
            else ret=G(ta,s,t,d);
        }
    }else {
        int dst=D(id,s,t),dsv=D(id,s,v),dtv=D(id,t,v);
        if(dst+dtv==dsv&&t>tr[ta].n)ret=(G(tb,s-tr[ta].n,t-tr[ta].n,d)+G(ta,u,u,0))%mod;
        else if(dsv+dst==dtv&&t>tr[ta].n&&d)ret=G(tb,s-tr[ta].n,t-tr[ta].n,d);
        else if(dsv+dtv==dst&&t<=tr[ta].n){
            if(d<=dsv)ret=(G(tb,s-tr[ta].n,v-tr[ta].n,d)+G(ta,u,t,0))%mod;
            else ret=G(ta,u,t,d-dsv-1);
        }else if(t>tr[ta].n){
            int al=(dsv+dst+dtv)/2;
            if(d+dtv<=al)ret=(G(tb,s-tr[ta].n,t-tr[ta].n,d)+G(ta,u,u,0))%mod;
            else ret=G(tb,s-tr[ta].n,t-tr[ta].n,d);
        }
    }return gm[GM(id,s,t,d)]=ret%mod;
}
signed main(){
    freopen("link.in","r",stdin);
    freopen("link.out","w",stdout);
    m=read();tr[0].n=1;tr[0].s0=tr[0].s1=1;
    fo(i,1,m){
        tr[i].ta=read();tr[i].tb=read();
        tr[i].x=read();tr[i].y=read();
        tr[i].n=tr[tr[i].ta].n+tr[tr[i].tb].n;
        int ns0,ns1,zj=0,now;
        now=D(i,tr[tr[i].ta].s0,tr[tr[i].ta].s1);
        if(now>zj)zj=now,ns0=tr[tr[i].ta].s0,ns1=tr[tr[i].ta].s1;
        now=D(i,tr[tr[i].tb].s0+tr[tr[i].ta].n,tr[tr[i].tb].s1+tr[tr[i].ta].n);
        if(now>zj)zj=now,ns0=tr[tr[i].tb].s0+tr[tr[i].ta].n,ns1=tr[tr[i].tb].s1+tr[tr[i].ta].n;
        now=D(i,tr[tr[i].ta].s0,tr[tr[i].tb].s0+tr[tr[i].ta].n);
        if(now>zj)zj=now,ns0=tr[tr[i].ta].s0,ns1=tr[tr[i].tb].s0+tr[tr[i].ta].n;
        now=D(i,tr[tr[i].ta].s0,tr[tr[i].tb].s1+tr[tr[i].ta].n);
        if(now>zj)zj=now,ns0=tr[tr[i].ta].s0,ns1=tr[tr[i].tb].s1+tr[tr[i].ta].n;
        now=D(i,tr[tr[i].ta].s1,tr[tr[i].tb].s0+tr[tr[i].ta].n);
        if(now>zj)zj=now,ns0=tr[tr[i].ta].s1,ns1=tr[tr[i].tb].s0+tr[tr[i].ta].n;
        now=D(i,tr[tr[i].ta].s1,tr[tr[i].tb].s1+tr[tr[i].ta].n);
        if(now>zj)zj=now,ns0=tr[tr[i].ta].s1,ns1=tr[tr[i].tb].s1+tr[tr[i].ta].n;
        tr[i].s0=ns0;tr[i].s1=ns1;int ans=0;
        if(zj&1){
            ans=(F(i,ns0,ns1,zj+1>>1)+F(i,ns1,ns0,zj+1>>1)+(tr[i].n%mod)*((zj+1>>1)%mod)%mod)%mod;
            printf("%lld\n",ans);
        }
        else {
            int tmp=G(i,ns0,ns1,zj>>1)%mod;
            ans=(F(i,ns0,ns1,zj>>1)+tmp*((zj>>1)%mod))%mod;
            ans=(ans+F(i,ns1,ns0,(zj>>1)+1)+((zj>>1)%mod+1)*((tr[i].n-tmp+mod)%mod)%mod)%mod;
            printf("%lld\n",ans);
        }
    }
}
不压行带注释
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=155;
const int mod=998244353;
int ksm(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=ret*x%mod;
        x=x*x%mod;y>>=1;
    }return ret;
}
int m;struct TREE{int n,ta,tb,x,y,s0,s1;}tr[N];
struct DM{
    int id,x,y;
    DM(){}
    DM(int a,int b,int c){id=a;x=b;y=c;}
    bool operator < (DM a)const{
        if(id!=a.id)return id<a.id;
        if(x!=a.x)return x<a.x;
        return y<a.y;
    }
};
map<DM,int> dm;
int D(int id,int x,int y){
    if(id==0||x==y)return 0;
    if(x>y)swap(x,y);
    if(dm.find(DM(id,x,y))!=dm.end())return dm[DM(id,x,y)];int ret;
    if(y<=tr[tr[id].ta].n)ret=D(tr[id].ta,x,y);
    else if(x<=tr[tr[id].ta].n&&y>tr[tr[id].ta].n)ret=D(tr[id].ta,x,tr[id].x)+D(tr[id].tb,tr[id].y,y-tr[tr[id].ta].n)+1;
    else if(x>tr[tr[id].ta].n)ret=D(tr[id].tb,x-tr[tr[id].ta].n,y-tr[tr[id].ta].n);
    return dm[DM(id,x,y)]=ret;
}
struct FM{
    int id,s,t,d;
    FM(){}
    FM(int a,int b,int c,int e){id=a;s=b;t=c;d=e;}
    bool operator < (FM a)const{
        if(id!=a.id)return id<a.id;
        if(s!=a.s)return s<a.s;
        if(t!=a.t)return t<a.t;
        return d<a.d;
    }
};
map<FM,int> fm;
int F(int id,int s,int t,int d){
    if(id==0)return 0;
    if(fm.find(FM(id,s,t,d))!=fm.end())return fm[FM(id,s,t,d)];
    int ret,u=tr[id].x,v=tr[id].y+tr[tr[id].ta].n,ta=tr[id].ta,tb=tr[id].tb;
    // cerr<<id<<" "<<s<<" "<<t<<" "<<d<<" "<<"FK"<<endl;
    if(D(id,s,u)<D(id,s,v)){
        // cerr<<id<<" "<<s<<" "<<t<<" "<<d<<" "<<u<<" "<<v<<endl;
        int dst=D(id,s,t),dsu=D(id,s,u),dtu=D(id,t,u);
        // cerr<<"SB"<<" "<<dst<<" "<<dsu<<" "<<dtu<<endl;
        // cerr<<id<<" "<<dsu<<" "<<dst<<" "<<dtu<<endl;
        if(dst+dtu==dsu&&t<=tr[ta].n){
            ret=(F(ta,s,t,d)+((dsu+1-d)%mod)*(tr[tb].n%mod)%mod+F(tb,v-tr[ta].n,v-tr[ta].n,0))%mod;
        }
        else if(dsu+dst==dtu&&t<=tr[ta].n&&d){
            // cerr<<"SB"<<endl;
            // cerr<<id<<endl;
            ret=F(ta,s,t,d);
        }
        else if(dsu+dtu==dst&&t>tr[ta].n){
            // cerr<<"SB"<<" "<<d<<" "<<dsu<<" OK ";
            if(d<=dsu){
                // cerr<<"ZZ"<<" ";
                ret=(F(ta,s,u,d)+((dsu+1-d)%mod)*(tr[tb].n%mod)%mod+F(tb,v-tr[ta].n,t-tr[ta].n,0))%mod;
            }
            else {
                ret=F(tb,v-tr[ta].n,t-tr[ta].n,d-dsu-1);
            }
        }
        else if(t<=tr[ta].n){
            int al=(dsu+dst+dtu)/2;
            if(d+dtu<=al){
                ret=(F(ta,s,t,d)+((dsu+1-d)%mod)*(tr[tb].n%mod)%mod+F(tb,v-tr[ta].n,v-tr[ta].n,0))%mod;
            }
            else {
                ret=F(ta,s,t,d);
            }
        }
    }
    else {
        // cerr<<"SB"<<" "<<id<<" "<<s<<" "<<t<<" "<<d<<" "<<u<<" "<<v<<endl;
        int dst=D(id,s,t),dsv=D(id,s,v),dtv=D(id,t,v);
        if(dst+dtv==dsv&&t>tr[ta].n){
            // cerr<<"ZZ"<<endl;
            ret=(F(tb,s-tr[ta].n,t-tr[ta].n,d)+((dsv+1-d)%mod)*(tr[ta].n%mod)%mod+F(ta,u,u,0))%mod;
        }
        else if(dsv+dst==dtv&&t>tr[ta].n&&d){
            ret=F(tb,s-tr[ta].n,t-tr[ta].n,d);
        }
        else if(dsv+dtv==dst&&t<=tr[ta].n){
            // cerr<<"zz "<<" "<<d<<" "<<dsv<<endl;
            if(d<=dsv){
                ret=(F(tb,s-tr[ta].n,v-tr[ta].n,d)+((dsv+1-d)%mod)*(tr[ta].n%mod)%mod+F(ta,u,t,0))%mod;
            }
            else {
                ret=F(ta,u,t,d-dsv-1);
            }
        }
        else if(t>tr[ta].n){
            int al=(dsv+dst+dtv)/2;
            if(d+dtv<=al){
                ret=(F(tb,s-tr[ta].n,t-tr[ta].n,d)+((dsv+1-d)%mod)*(tr[ta].n%mod)%mod+F(ta,u,u,0))%mod;
            }
            else {
                ret=F(tb,s-tr[ta].n,t-tr[ta].n,d);
            }
        }
    }
    // cerr<<id<<" "<<s<<" "<<t<<" "<<d<<" "<<ret<<endl;
    return fm[FM(id,s,t,d)]=ret%mod;
}
struct GM{
    int id,s,t,d;
    GM(){}
    GM(int a,int b,int c,int e){id=a;s=b;t=c;d=e;}
    bool operator < (GM a)const{
        if(id!=a.id)return id<a.id;
        if(s!=a.s)return s<a.s;
        if(t!=a.t)return t<a.t;
        return d<a.d;
    }
};
map<GM,int> gm;
int G(int id,int s,int t,int d){
    if(id==0)return 1;
    if(gm.find(GM(id,s,t,d))!=gm.end())return gm[GM(id,s,t,d)];
    int ret,u=tr[id].x,v=tr[id].y+tr[tr[id].ta].n,ta=tr[id].ta,tb=tr[id].tb;
    // cerr<<id<<" "<<s<<" "<<t<<" "<<d<<" "<<"FK"<<endl;
    if(D(id,s,u)<D(id,s,v)){
        // cerr<<id<<" "<<s<<" "<<t<<" "<<d<<" "<<u<<" "<<v<<endl;
        int dst=D(id,s,t),dsu=D(id,s,u),dtu=D(id,t,u);
        // cerr<<"SB"<<" "<<dst<<" "<<dsu<<" "<<dtu<<endl;
        // cerr<<id<<" "<<dsu<<" "<<dst<<" "<<dtu<<endl;
        if(dst+dtu==dsu&&t<=tr[ta].n){
            ret=(G(ta,s,t,d)+G(tb,v-tr[ta].n,v-tr[ta].n,0))%mod;
        }
        else if(dsu+dst==dtu&&t<=tr[ta].n&&d){
            // cerr<<"SB"<<endl;
            // cerr<<id<<endl;
            ret=G(ta,s,t,d);
        }
        else if(dsu+dtu==dst&&t>tr[ta].n){
            // cerr<<"SB"<<" "<<d<<" "<<dsu<<" OK ";
            if(d<=dsu){
                // cerr<<"ZZ"<<" ";
                ret=(G(ta,s,u,d)+G(tb,v-tr[ta].n,t-tr[ta].n,0))%mod;
            }
            else {
                ret=G(tb,v-tr[ta].n,t-tr[ta].n,d-dsu-1);
            }
        }
        else if(t<=tr[ta].n){
            int al=(dsu+dst+dtu)/2;
            if(d+dtu<=al){
                ret=(G(ta,s,t,d)+G(tb,v-tr[ta].n,v-tr[ta].n,0))%mod;
            }
            else {
                ret=G(ta,s,t,d);
            }
        }
    }
    else {
        // cerr<<"SB"<<" "<<id<<" "<<s<<" "<<t<<" "<<d<<" "<<u<<" "<<v<<endl;
        int dst=D(id,s,t),dsv=D(id,s,v),dtv=D(id,t,v);
        if(dst+dtv==dsv&&t>tr[ta].n){
            // cerr<<"ZZ"<<endl;
            ret=(G(tb,s-tr[ta].n,t-tr[ta].n,d)+G(ta,u,u,0))%mod;
        }
        else if(dsv+dst==dtv&&t>tr[ta].n&&d){
            ret=G(tb,s-tr[ta].n,t-tr[ta].n,d);
        }
        else if(dsv+dtv==dst&&t<=tr[ta].n){
            // cerr<<"zz "<<" "<<d<<" "<<dsv<<endl;
            if(d<=dsv){
                ret=(G(tb,s-tr[ta].n,v-tr[ta].n,d)+G(ta,u,t,0))%mod;
            }
            else {
                ret=G(ta,u,t,d-dsv-1);
            }
        }
        else if(t>tr[ta].n){
            int al=(dsv+dst+dtv)/2;
            if(d+dtv<=al){
                ret=(G(tb,s-tr[ta].n,t-tr[ta].n,d)+G(ta,u,u,0))%mod;
            }
            else {
                ret=G(tb,s-tr[ta].n,t-tr[ta].n,d);
            }
        }
    }
    // cerr<<id<<" "<<s<<" "<<t<<" "<<d<<" "<<ret<<endl;
    return gm[GM(id,s,t,d)]=ret%mod;
}
signed main(){
    freopen("link.in","r",stdin);
    freopen("link.out","w",stdout);
    m=read();tr[0].n=1;tr[0].s0=tr[0].s1=1;
    fo(i,1,m){
        tr[i].ta=read();tr[i].tb=read();
        tr[i].x=read();tr[i].y=read();
        tr[i].n=tr[tr[i].ta].n+tr[tr[i].tb].n;
        int ns0,ns1,zj=0,now;
        now=D(i,tr[tr[i].ta].s0,tr[tr[i].ta].s1);
        if(now>zj)zj=now,ns0=tr[tr[i].ta].s0,ns1=tr[tr[i].ta].s1;
        now=D(i,tr[tr[i].tb].s0+tr[tr[i].ta].n,tr[tr[i].tb].s1+tr[tr[i].ta].n);
        if(now>zj)zj=now,ns0=tr[tr[i].tb].s0+tr[tr[i].ta].n,ns1=tr[tr[i].tb].s1+tr[tr[i].ta].n;
        now=D(i,tr[tr[i].ta].s0,tr[tr[i].tb].s0+tr[tr[i].ta].n);
        if(now>zj)zj=now,ns0=tr[tr[i].ta].s0,ns1=tr[tr[i].tb].s0+tr[tr[i].ta].n;
        now=D(i,tr[tr[i].ta].s0,tr[tr[i].tb].s1+tr[tr[i].ta].n);
        if(now>zj)zj=now,ns0=tr[tr[i].ta].s0,ns1=tr[tr[i].tb].s1+tr[tr[i].ta].n;
        now=D(i,tr[tr[i].ta].s1,tr[tr[i].tb].s0+tr[tr[i].ta].n);
        if(now>zj)zj=now,ns0=tr[tr[i].ta].s1,ns1=tr[tr[i].tb].s0+tr[tr[i].ta].n;
        now=D(i,tr[tr[i].ta].s1,tr[tr[i].tb].s1+tr[tr[i].ta].n);
        if(now>zj)zj=now,ns0=tr[tr[i].ta].s1,ns1=tr[tr[i].tb].s1+tr[tr[i].ta].n;
        tr[i].s0=ns0;tr[i].s1=ns1;int ans=0;
        // cerr<<"zj "<<zj<<" "<<ns0<<" "<<ns1<<endl;
        // cerr<<"--------------------------------"<<" "<<i<<endl;
        if(zj&1){
            // cerr<<F(i,ns0,ns1,zj+1>>1)<<" "<<F(i,ns1,ns0,zj+1>>1)<<endl;
            ans=(F(i,ns0,ns1,zj+1>>1)+F(i,ns1,ns0,zj+1>>1)+(tr[i].n%mod)*((zj+1>>1)%mod)%mod)%mod;
            printf("%lld\n",ans);
        }
        else {
            int tmp=G(i,ns0,ns1,zj>>1)%mod;
            ans=(F(i,ns0,ns1,zj>>1)+tmp*((zj>>1)%mod))%mod;
            ans=(ans+F(i,ns1,ns0,(zj>>1)+1)+((zj>>1)%mod+1)*((tr[i].n-tmp+mod)%mod)%mod)%mod;
            printf("%lld\n",ans);
        }
    }
}
posted @ 2022-03-18 19:00  fengwu2005  阅读(32)  评论(0编辑  收藏  举报