zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Linux关闭jetty服务器脚本
    TreeMap 源码解读
    LinkedHashMap 源码解读
    HashTable 源码解读
    MappedByteBuffer文件句柄释放问题
    HashMap源码解读
    Java 对象创建过程
    java 虚拟机内存介绍
    dubbo 部署
    kotlin 学习入门
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9697009.html
Copyright © 2011-2022 走看看