分析:
考场上没来得及看
其实也不难
点分治水水就过了
每次加入链最大值最小的,这样每次加入时,能够保证它是所有已加入点的最大值。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 100010
#define MAXP 10000010
using namespace std;
typedef long long ll;
vector<int> a[MAXN];
int n,P;
ll ans;
bool used[MAXN];
int siz[MAXN],siz1[MAXN];
void dfs(int x,int fa=0){
siz[x]=1;
for(int i=0;i<int(a[x].size());i++){
int u=a[x][i];
if(u==fa||used[u])
continue;
dfs(u,x);
siz[x]+=siz[u];
}
}
int get_siz(int x,int siztot,int fa=0){
int g=0;
siz1[x]=siztot-siz[x];
for(int i=0;i<int(a[x].size());i++){
int u=a[x][i];
if(u==fa||used[u])
continue;
int g1=get_siz(u,siztot,x);
siz1[x]=max(siz1[x],siz[u]);
if(g==0||siz1[g]>siz1[g1])
g=g1;
}
if(g==0||siz1[g]>siz1[x])
g=x;
return g;
}
int find_g(int x){
dfs(x);
return get_siz(x,siz[x]);
}
struct node{
int u,maxv,fa,sumv;
node () {}
node (int u1,int maxv1,int sumv1,int fa1):u(u1),maxv(maxv1),sumv(sumv1),fa(fa1) {}
bool operator <(const node &a) const{
return maxv>a.maxv;
}
};
priority_queue<node>q;
int val[MAXN],totv[MAXP];
int st[MAXN],tp;
int calc(int x,int fa=0){
int g=x;
if(fa==0)
q.push(node(x,val[x],val[x]%P,0));
else
q.push(node(x,max(val[x],val[fa]),(val[x]+val[fa])%P,fa));
if(fa)
g=fa;
ll res=0;
while(!q.empty()){
node newp=q.top();
q.pop();
int x=newp.u;
res+=totv[(newp.maxv-newp.sumv+P+val[g])%P];
// PF("{%d %d %d %d}\n",x,totv[(newp.maxv-newp.sumv+P+val[g])%P],newp.maxv,newp.sumv);
totv[newp.sumv]++;
st[++tp]=newp.sumv;
for(int i=0;i<int(a[x].size());i++){
int u=a[x][i];
if(u==newp.fa||used[u])
continue;
q.push(node(u,max(newp.maxv,val[u]),(newp.sumv+val[u])%P,x));
}
}
while(tp)
totv[st[tp--]]--;
return res;
}
void solve(int x){
int g=find_g(x);
// PF("[%d]\n",g);
used[g]=1;
ans+=calc(g);
ans++;
// PF("[%d %lld]\n",g,ans);
for(int i=0;i<int(a[g].size());i++){
int u=a[g][i];
if(used[u])
continue;
ans-=calc(u,g);
}
// PF("<%d %lld>\n",g,ans);
for(int i=0;i<int(a[g].size());i++){
int u=a[g][i];
if(used[u])
continue;
solve(u);
}
}
int main(){
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
SF("%d%d",&n,&P);
int u,v;
for(int i=1;i<n;i++){
SF("%d%d",&u,&v);
a[u].push_back(v);
a[v].push_back(u);
}
for(int i=1;i<=n;i++){
SF("%d",&val[i]);
}
solve(1);
PF("%lld",ans);
}