NOIP2016 天天爱跑步 (树上差分+dfs)

题目大意:给你一颗树,树上每个点都有一个观察员,他们仅会在 w[i] 时刻出现,观察正在跑步的玩家

一共有m个玩家,他们分别从节点 s[i] 同时出发,以每秒跑一条边的速度,沿着到 t[i] 的唯一路径向节点t[i]奔跑

如果一名玩家已经到达了终点,那么在他到达终点之后出现在终点的观察员不会观察到他

但如果在到达终点的同时观察员也出现在终点,那么观察员可以观察到他

求每个节点的观察员观察到玩家的数量

对于每个玩家的奔跑路线,可以拆成两部分

<1>向上跑,从 u 向 lca 奔跑

显然,玩家 u 能对观察员 i 产生1点贡献的充要条件为

deep[u]=deep[i]+w[i]

显然,向上走的路线能对 i 点产生共贡献的条件是,起点 u 在 i 的子树中

我们只需要统计符合条件的deep[u]即可

<2>向下跑,从 lca 向 v 奔跑

那么显然dis<u,v>-dis<i,v>=w[i]

推导可得deep[u]-2*deep[lca]=w[i]-deep[i]

显然,向下走的路线能对i点产生共贡献的条件是,终点 v 在 i 的子树中

类似于上面的方法,我们只需要统计符合条件的deep[u]-2*deep[lca]即可

我们可以用vector在u,v,lca这三个点上打差分,存符合条件的值,注意值可能为负数

而其他子树的结果会影响答案,所以深搜统计一次答案,再用回溯的答案减去深搜的答案即可

方法比较奇葩大家凑合看吧。。。

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <vector>
  5 #define N 300010
  6 #define maxn 300000
  7 using namespace std;
  8 
  9 int n,m,cte;
 10 int dep[N],fa[N],tp[N],sz[N],son[N],ans[N];
 11 int w[N],s[N],t[N],F[N],bac[N*3],head[N],tmp[N];
 12 struct EDGE{
 13     int to,nxt;
 14 }edge[N*2];
 15 vector<int>S[N];
 16 vector<int>E[N];
 17 int gc()
 18 {
 19     int rett=0,fh=1;char p=getchar();
 20     while(p<'0'||p>'9') {if(p=='-')fh=-1;p=getchar();}
 21     while(p>='0'&&p<='9') {rett=rett*10+p-'0';p=getchar();}
 22     return rett*fh;
 23 }
 24 void edge_add(int u,int v)
 25 {
 26     cte++;
 27     edge[cte].to = v;
 28     edge[cte].nxt=head[u];
 29     head[u]=cte;
 30 }
 31 void Tsp1(int u,int dad)
 32 {
 33     for(int j=head[u];j!=-1;j=edge[j].nxt)
 34     {
 35         int v=edge[j].to;
 36         if(v==dad) continue;
 37         dep[v]=dep[u]+1;
 38         fa[v]=u;
 39         Tsp1(v,u);
 40         if(sz[v]>sz[son[u]]) son[u]=v;
 41         sz[u]+=sz[v];
 42     }
 43     sz[u]++;
 44 }
 45 void Tsp2(int u)
 46 {
 47     if(son[u]) tp[son[u]]=tp[u],Tsp2(son[u]);
 48     for(int j=head[u];j!=-1;j=edge[j].nxt)
 49     {
 50         int v=edge[j].to;
 51         if(v==fa[u]||v==son[u]) continue;
 52         tp[v]=v;
 53         Tsp2(v);
 54     }
 55 }
 56 int LCA(int x,int y)
 57 {
 58     while(tp[x]!=tp[y])
 59     {
 60         if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
 61         x=fa[tp[x]];
 62     }
 63     return dep[x]<=dep[y]?x:y;
 64 }
 65 void dfs1(int u)
 66 {
 67     tmp[u]=bac[dep[u]+w[u]+maxn];
 68     for(int j=head[u];j!=-1;j=edge[j].nxt)
 69     {
 70         int v=edge[j].to;
 71         if(v==fa[u]) continue;
 72         dfs1(v);
 73     }
 74     for(int i=0;i<S[u].size();i++)
 75         bac[S[u][i]+maxn]++;
 76     ans[u]+=bac[dep[u]+w[u]+maxn]-tmp[u];
 77     for(int i=0;i<E[u].size();i++)
 78         bac[E[u][i]+maxn]--;
 79 }
 80 void dfs2(int u)
 81 {
 82     tmp[u]=bac[w[u]-dep[u]+maxn];
 83     for(int j=head[u];j!=-1;j=edge[j].nxt)
 84     {
 85         int v=edge[j].to;
 86         if(v==fa[u]) continue;
 87         dfs2(v);
 88     }
 89     for(int i=0;i<E[u].size();i++)
 90         bac[E[u][i]+maxn]--;
 91     for(int i=0;i<S[u].size();i++)
 92         bac[S[u][i]+maxn]++;
 93     ans[u]+=bac[w[u]-dep[u]+maxn]-tmp[u];
 94 }
 95 
 96 int main()
 97 {
 98     freopen("running1.in","r",stdin);
 99     //freopen("running6.out","w",stdout);
100     scanf("%d%d",&n,&m);
101     int x,y;
102     memset(head,-1,sizeof(head));
103     for(int i=1;i<n;i++)
104     {
105         x=gc(),y=gc();
106         edge_add(x,y);
107         edge_add(y,x);
108     }
109     tp[1]=1;
110     Tsp1(1,-1);
111     Tsp2(1);
112     for(int i=1;i<=n;i++) w[i]=gc();
113     for(int i=1;i<=m;i++)
114     {
115         s[i]=gc(),t[i]=gc();
116         F[i]=LCA(s[i],t[i]);
117         S[s[i]].push_back(dep[s[i]]);
118         E[F[i]].push_back(dep[s[i]]);
119     }
120     //debug();
121     dfs1(1);
122     for(int i=1;i<=n;i++) 
123     {
124         S[i].clear(),E[i].clear();
125     }
126     memset(tmp,0,sizeof(tmp));
127     for(int i=1;i<=m;i++)
128     {
129         S[t[i]].push_back(dep[s[i]]-2*dep[F[i]]);
130         E[F[i]].push_back(dep[s[i]]-2*dep[F[i]]);
131     }
132     dfs2(1);
133     for(int i=1;i<=n;i++) printf("%d ",ans[i]);
134     return 0;
135 }
原文地址:https://www.cnblogs.com/guapisolo/p/9697009.html