洛谷 P1600 天天爱跑步(LCA+乱搞)

传送门

我们把每一条路径拆成$u->lca$和$lca->v$的路径

先考虑$u->lca$,如果这条路径会对路径上的某一个点产生贡献,那么满足$dep[u]-dep[x]=w[x],dep[u]=dep[x]+w[x]$,注意到$dep[x]+w[x]$是一个定值,所以我们只要去找它的子树里有多少个点的$dep$等于$dep[x]+w[x]$就可以了,这个可以直接开一个桶。然而如果点$x$在$lca$的上面,这一条路径是不会对他产生贡献的,那么我们就得在$lca$处把这一条路径的贡献给减去。具体怎么做呢?我们可以利用树上差分的思想,在点$u$把它的出现次数$+1$,在$lca$处把它的出现次数$-1$,那么我们对于每一个点,只要去查询它的子树里$dep[x]+w[x]$这个值出现了多少次就可以了。

顺便注意一下,因为我们的桶里存的不止是一棵子树的答案,所以查询得到的次数可能是来子其他子树的。那么我们可以dfs进去之前先记录一下,完了之后再记录一下,两次的差就是这个值在其子树里的实际出现次数

然后$lca->v$的路径咋搞嘞?只要把式子改成$dep[v]-dep[x]=len-w[i]$($len$表示路径长度),然后和上面一样的做法。注意这里有可能会出现负数,所以我们要让它加上$3e5$

注意到$lca$会被我们统计两次,那么我们只要最后做完之后,把所有被统计了两次答案的$lca$答案减一就好了

  1 //minamoto
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<algorithm>
  5 #include<vector>
  6 using namespace std;
  7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
  8 char buf[1<<21],*p1=buf,*p2=buf;
  9 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
 10 inline int read(){
 11     #define num ch-'0'
 12     char ch;bool flag=0;int res;
 13     while(!isdigit(ch=getc()))
 14     (ch=='-')&&(flag=true);
 15     for(res=num;isdigit(ch=getc());res=res*10+num);
 16     (flag)&&(res=-res);
 17     #undef num
 18     return res;
 19 }
 20 char sr[1<<21],z[20];int C=-1,Z;
 21 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
 22 inline void print(int x){
 23     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
 24     while(z[++Z]=x%10+48,x/=10);
 25     while(sr[++C]=z[Z],--Z);sr[++C]=' ';
 26 }
 27 const int N=300005,M=600005;
 28 int head[N],Next[M],ver[M],tot;
 29 int son[N],sz[N],fa[N],dep[N],top[N];
 30 int c[N],w[N],val[N],num[1000005];
 31 int n,m,lim,ans[N];
 32 vector<int> qaq[N],qaq2[N],qaq3[N];
 33 struct node{int s,t,lca,len;}q[N];
 34 inline void add(int u,int v){
 35     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
 36     ver[++tot]=u,Next[tot]=head[v],head[v]=tot;
 37 }
 38 void dfs1(int u){
 39     sz[u]=1,dep[u]=dep[fa[u]]+1,cmax(lim,dep[u]);
 40     for(int i=head[u];i;i=Next[i]){
 41         int v=ver[i];
 42         if(v!=fa[u]){
 43             fa[v]=u,dfs1(v),sz[u]+=sz[v];
 44             if(sz[v]>sz[son[u]]) son[u]=v;
 45         }
 46     }
 47 }
 48 void dfs2(int u,int t){
 49     top[u]=t;
 50     if(son[u]) dfs2(son[u],t);else return;
 51     for(int i=head[u];i;i=Next[i]){
 52         int v=ver[i];
 53         if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
 54     }
 55 }
 56 inline int LCA(int u,int v){
 57     while(top[u]!=top[v]){
 58         if(dep[top[u]]<dep[top[v]]) swap(u,v);u=fa[top[u]];
 59     }
 60     return dep[u]<dep[v]?u:v;
 61 }
 62 void dfs(int u,int fa){
 63     int now=w[u]+dep[u],k;if(now<=lim) k=c[now];
 64     for(int i=head[u];i;i=Next[i]){
 65         int v=ver[i];if(v!=fa) dfs(v,u);
 66     }
 67     c[dep[u]]+=val[u];if(now<=lim) ans[u]=c[now]-k;
 68     for(int i=0,s=qaq[u].size();i<s;++i) --c[dep[qaq[u][i]]];
 69 }
 70 void DFS(int u,int fa){
 71     int now=dep[u]-w[u],k;now+=300000,k=num[now];
 72     for(int i=head[u];i;i=Next[i]){
 73         int v=ver[i];if(v!=fa) DFS(v,u);
 74     }
 75     for(int i=0,s=qaq2[u].size();i<s;++i) ++num[300000+qaq2[u][i]];
 76     ans[u]+=num[now]-k;
 77     for(int i=0,s=qaq3[u].size();i<s;++i) --num[300000+qaq3[u][i]];
 78 }
 79 int main(){
 80     //freopen("testdata.in","r",stdin);
 81     n=read(),m=read();
 82     for(int i=1;i<n;++i){
 83         int u=read(),v=read();add(u,v);
 84     }
 85     for(int i=1;i<=n;++i) w[i]=read();
 86     dfs1(1),dfs2(1,1);
 87     for(int i=1;i<=m;++i){
 88         q[i].s=read(),q[i].t=read(),++val[q[i].s];
 89         q[i].lca=LCA(q[i].s,q[i].t),q[i].len=dep[q[i].s]+dep[q[i].t]-dep[q[i].lca]*2;
 90         qaq[q[i].lca].push_back(q[i].s);
 91     }
 92     dfs(1,0);
 93     for(int i=1;i<=m;++i){
 94         qaq2[q[i].t].push_back(dep[q[i].t]-q[i].len);
 95         qaq3[q[i].lca].push_back(dep[q[i].t]-q[i].len);
 96     }
 97     DFS(1,0);
 98     for(int i=1;i<=m;++i) if(dep[q[i].s]-dep[q[i].lca]==w[q[i].lca]) --ans[q[i].lca];
 99     for(int i=1;i<=n;++i) print(ans[i]);
100     Ot();
101     return 0;
102 }

猜你喜欢

转载自www.cnblogs.com/bztMinamoto/p/9563834.html