wannfly挑战赛24E

传送门

直接离线点分+背包,记得询问得挂到点分树的\(LCA\)

//quming
#include<bits/stdc++.h>
#define R register
#define pb emplace_back
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(head,u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int P=998244353;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int inc(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
    R int res=1;
    for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
    return res;
}
const int N=2e5+5;
struct eg{int v,nx;}e[N<<2];int head[N],hc[N],tot;
inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
inline void ADD(R int u,R int v){e[++tot]={v,hc[u]},hc[u]=tot;}
struct node{
    int u,v,id;
    inline node(R int uu,R int vv,R int ii):u(uu),v(vv),id(ii){}
};
vector<node>qr[N];
int fa[N],dep[N],sz[N],mx[N],ans[N],a[N],f[N][55],g[N][55];
int rt,size,n,L,q,Rt;
void findrt(int u,int fa){
    sz[u]=1,mx[u]=0;
    go(head,u)if(v!=fa&&!dep[v])findrt(v,u),sz[u]+=sz[v],cmax(mx[u],sz[v]);
    cmax(mx[u],size-sz[u]);
    if(mx[u]<mx[rt])rt=u;
}
void solve(int u){
    dep[u]=dep[fa[u]]+1;
    R int s=size;
    go(head,u)if(!dep[v]){
        size=(sz[v]>sz[u]?s-sz[u]:sz[v]),rt=0;
        findrt(v,u),fa[rt]=u,ADD(u,rt),solve(rt);
    }
}
inline int LCA(R int u,R int v){
    while(u!=v)dep[u]>dep[v]?u=fa[u]:v=fa[v];
    return u;
}
void get(int u,int fa,int d){
    go(head,u)if(v!=fa&&dep[v]>=d){
        memset(g[v],0,L<<2);
        memset(f[v],0,L<<2);
        for(R int i=0,j=a[v];i<L;++i,++j){
            upd(f[v][i],f[u][i]),upd(f[v][j],f[u][i]);
            upd(g[v][i],g[u][i]),upd(g[v][j],g[u][i]);
            if(j==L-1)j=-1;
        }
        get(v,u,d);
    }
}
inline int calc(R int u,R int v){
    R int res=mul(f[u][0],g[v][0]);
    fp(i,1,L-1)upd(res,mul(f[u][i],g[v][L-i]));
    return res;
}
void dfs(int u){
    if(!qr[u].empty()){
        memset(g[u],0,L<<2);
        memset(f[u],0,L<<2);
        g[u][0]=f[u][0]=1,++f[u][a[u]];
        get(u,0,dep[u]);
        for(auto w:qr[u])ans[w.id]=calc(w.u,w.v);
    }
    go(hc,u)dfs(v);
}
int main(){
//  freopen("testdata.in","r",stdin);
    scanf("%d%d",&n,&L);
    for(R int i=1,u,v;i<n;++i)scanf("%d%d",&u,&v),add(u,v),add(v,u);
    fp(i,1,n)scanf("%d",&a[i]),a[i]%=L;
    mx[0]=n+1,rt=0,size=n,findrt(1,0),solve(Rt=rt);
    scanf("%d",&q);
    for(R int i=1,u,v;i<=q;++i){
        scanf("%d%d",&u,&v);
        qr[LCA(u,v)].pb(node(u,v,i));
    }
    dfs(Rt);
    fp(i,1,q)printf("%d\n",ans[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/yuanquming/p/11711347.html