zoukankan      html  css  js  c++  java
  • [BZOJ4719][Noip2016]天天爱跑步

    4719: [Noip2016]天天爱跑步

    Time Limit: 40 Sec  Memory Limit: 512 MB
    Submit: 934  Solved: 304
    [Submit][Status][Discuss]

    Description

    小c同学认为跑步非常有趣,于是决定制作一款叫做《天天爱跑步》的游戏。?天天爱跑步?是一个养成类游戏,需要
    玩家每天按时上线,完成打卡任务。这个游戏的地图可以看作一一棵包含 N个结点和N-1 条边的树, 每条边连接两
    个结点,且任意两个结点存在一条路径互相可达。树上结点编号为从1到N的连续正整数。现在有个玩家,第个玩家的
    起点为Si ,终点为Ti  。每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发, 以每秒跑一条边的速度,
    不间断地沿着最短路径向着自己的终点跑去, 跑到终点后该玩家就算完成了打卡任务。 (由于地图是一棵树, 所以
    每个人的路径是唯一的)小C想知道游戏的活跃度, 所以在每个结点上都放置了一个观察员。 在结点的观察员会选
    择在第Wj秒观察玩家, 一个玩家能被这个观察员观察到当且仅当该玩家在第Wj秒也理到达了结点J  。 小C想知道
    每个观察员会观察到多少人?注意: 我们认为一个玩家到达自己的终点后该玩家就会结束游戏, 他不能等待一 段时
    间后再被观察员观察到。 即对于把结点J作为终点的玩家: 若他在第Wj秒重到达终点,则在结点J的观察员不能观察
    到该玩家;若他正好在第Wj秒到达终点,则在结点的观察员可以观察到这个玩家。

    Input

    第一行有两个整数N和M 。其中N代表树的结点数量, 同时也是观察员的数量, M代表玩家的数量。
    接下来n-1 行每行两个整数U和V ,表示结点U 到结点V 有一条边。
    接下来一行N 个整数,其中第个整数为Wj , 表示结点出现观察员的时间。
    接下来 M行,每行两个整数Si和Ti,表示一个玩家的起点和终点。
    对于所有的数据,保证 。
    1<=Si,Ti<=N,0<=Wj<=N
     

    Output

    输出1行N 个整数,第个整数表示结点的观察员可以观察到多少人。

     

    Sample Input

    6 3
    2 3
    1 2
    1 4
    4 5
    4 6
    0 2 5 1 2 3
    1 5
    1 3
    2 6

    Sample Output

    2 0 0 1 1 1

    HINT


    对于1号点,W1=0,故只有起点为1号点的玩家才会被观察到,所以玩家1和玩家2被观察到,共2人被观察到。

    对于2号点,没有玩家在第2秒时在此结点,共0人被观察到。

    对于3号点,没有玩家在第5秒时在此结点,共0人被观察到。

    对于4号点,玩家1被观察到,共1人被观察到。

    对于5号点,玩家1被观察到,共1人被观察到。

    对于6号点,玩家3被观察到,共1人被观察到
     
     
     
     

    天天爱跑步这题自从去年提高组以来一直便是我的一块心里阴影。今天终于下定决心去填坑。

    首先要求树上两点间的最短距离,毫无疑问要用到lca,此处懒惰的我用了最好写的倍增。
    随后我们分析每一条路径(x,y),发现他能拆分成x->lca(x,y)和lca(x,y)->y两条链。

    对于每一条x->lca(x,y)上的点now,他能观察到此人当且仅当deep[x]=deep[now]+w[now];

    同样的对于每条lca(x,y)->y上的点,他能观察到此人当且仅当deep[y]-t=deep[now]-w[now];其中t为x->y的路径长度。

    这时我们发现等式一边只与当前节点的deep有关,等式右边只与询问节点的deep和w有关,所以我们想到用一个桶打标记。

    利用dfs序的性质,在一个点x入栈时,将deep[x]放入桶中,当lca(x,y)出栈时,使deep[x]出栈。

    在y入栈时,将deep[y]-t+30000放入栈中(因为deep[y]-t可能<0),当lca(x,y)出栈时,使deep[y]-t+300000出栈。

    对于每一个点,询问deep[now]+w[now]和deep[now]-w[now]+300000的桶中的数的个数。

    但值得注意的是,这样统计对于路径有多余计算,所以要在该节点入栈时记录初始值,在该点出栈时记录结束值以此保证所有计算的点都经过该路径。

    同时,当lca(x,y)能观察到从x出发的人时,这个人会被算两边,因此此处需要特判。

    下面是AC代码:

     1 #include<cstring>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<iostream>
     5 #include<cmath>
     6 #include<algorithm>
     7 using namespace std;
     8 int n,m;
     9 struct data
    10 {
    11     int to,next;
    12 }a[600001],upj[600001],downa[600001],downj[600001];
    13 int c[300001];
    14 int headupj[300001],headdowna[300001],headdownj[300001];
    15 int cntupj,cntdowna,cntdownj;
    16 int head[300001],cnt;
    17 int f[300001][21];
    18 int deep[300001];
    19 int w[300001];
    20 int up[600101],down[600101];
    21 int ans[300001];
    22 void add(int u,int v){a[cnt].next=head[u];a[cnt].to=v;head[u]=cnt;cnt++;}
    23 void addupj(int u,int v){upj[cntupj].next=headupj[u];upj[cntupj].to=v;headupj[u]=cntupj;cntupj++;}
    24 void adddowna(int u,int v){downa[cntdowna].next=headdowna[u];downa[cntdowna].to=v;headdowna[u]=cntdowna;cntdowna++;}
    25 void adddownj(int u,int v){downj[cntdownj].next=headdownj[u];downj[cntdownj].to=v;headdownj[u]=cntdownj;cntdownj++;}
    26 void dfs(int now,int fa,int d)
    27 {
    28     deep[now]=d;
    29     f[now][0]=fa;
    30     //cout<<now<<endl;
    31     for(int i=1;i<=20&&((1<<i)<=deep[now]);i++) f[now][i]=f[f[now][i-1]][i-1];
    32     for(int i=head[now];i>=0;i=a[i].next)
    33         if(a[i].to!=fa) dfs(a[i].to,now,d+1);
    34 }  
    35 int lca(int x,int y)
    36 {
    37     if(deep[x]<deep[y]) swap(x,y);
    38     int t=deep[x]-deep[y];
    39     for(int i=20;i>=0;i--)if((1<<i)&t) x=f[x][i];
    40     for(int i=20;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    41     return x==y?x:f[x][0];
    42 }
    43 void dfs1(int now,int fa)
    44 {
    45     int u=up[w[now]+deep[now]],v=down[deep[now]-w[now]+300005];
    46     up[deep[now]]+=c[now];
    47     for(int i=headdowna[now];i>=0;i=downa[i].next) down[downa[i].to]++;
    48     for(int i=head[now];i>=0;i=a[i].next) if(a[i].to!=fa) dfs1(a[i].to,now);
    49     ans[now]=up[w[now]+deep[now]]+down[deep[now]-w[now]+300005]-u-v;
    50     for(int i=headupj[now];i>=0;i=upj[i].next){up[upj[i].to]--;if(w[now]+deep[now]==upj[i].to) ans[now]--;}
    51     for(int i=headdownj[now];i>=0;i=downj[i].next) down[downj[i].to]--;
    52 }
    53 int main()
    54 {
    55     //freopen("running.in","r",stdin);
    56     //freopen("running.out","w",stdout);
    57     memset(head,-1,sizeof(head));
    58     memset(headdowna,-1,sizeof(headdowna));
    59     memset(headdownj,-1,sizeof(headdownj));
    60     memset(headupj,-1,sizeof(headupj));
    61     scanf("%d%d",&n,&m);
    62     for(int i=1;i<n;i++)
    63     {
    64         int u,v;
    65         scanf("%d%d",&u,&v);
    66         add(u,v);
    67         add(v,u);
    68     }
    69     //cout<<1;
    70     dfs(1,0,0);
    71     /*for(int i=1;i<=n;i++)
    72     for(int j=1;j<=20;j++)
    73         cout<<i<<' '<<j<<' '<<f[i][j]<<endl;
    74     /*for(int j=1;j<=20;j++)
    75        for(int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1];*/
    76     for(int i=1;i<=n;i++) scanf("%d",&w[i]);
    77     //cout<<1;
    78     for(int i=1;i<=m;i++)
    79     {
    80         int x,y;
    81         scanf("%d%d",&x,&y);
    82         c[x]++;
    83         int LCA=lca(x,y);
    84         int t=deep[y]+deep[x]-2*deep[LCA];
    85         int d=deep[y]-t+300005;
    86         addupj(LCA,deep[x]);
    87         adddowna(y,d);
    88         adddownj(LCA,d);
    89     }
    90     //cout<<1;
    91     dfs1(1,0);
    92     for(int i=1;i<n;i++) printf("%d ",ans[i]);
    93     printf("%d",ans[n]);
    94 }
    View Code
    O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~
  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    Activiti任务参数和流程参数的对比
    Intel x710万兆 SR-IOV 网卡驱动升级
    git clone分支到本地
    资源丨MySQL故障排查思路方法PPT&视频&24问答
    win10系统端口转发
  • 原文地址:https://www.cnblogs.com/wls001/p/7198575.html
Copyright © 2011-2022 走看看