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

    题目描述

    小c同学认为跑步非常有趣,于是决定制作一款叫做《天天爱跑步》的游戏。天天爱跑步是一个养成类游戏,需要 玩家每天按时上线,完成打卡任务。

    这个游戏的地图可以看作一一棵包含 N个结点和N-1 条边的树, 每条边连接两个结点,且任意两个结点存在一条路径互相可达。树上结点编号为从1到N的连续正整数。

    现在有个玩家,第个玩家的 起点为Si ,终点为Ti 。每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发, 以每秒跑一条边的速度, 不间断地沿着最短路径向着自己的终点跑去, 跑到终点后该玩家就算完成了打卡任务。 (由于地图是一棵树, 所以 每个人的路径是唯一的)

    小C想知道游戏的活跃度, 所以在每个结点上都放置了一个观察员。 在结点的观察员会选 择在第Wj秒观察玩家, 一个玩家能被这个观察员观察到当且仅当该玩家在第Wj秒也正好到达了结点J 。 小C想知道 每个观察员会观察到多少人?

    注意: 我们认为一个玩家到达自己的终点后该玩家就会结束游戏, 他不能等待一 段时 间后再被观察员观察到。 即对于把结点J作为终点的玩家: 若他在第Wj秒重到达终点,则在结点J的观察员不能观察 到该玩家;若他正好在第Wj秒到达终点,则在结点的观察员可以观察到这个玩家。

     。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

    题解开始:

    一眼看出将每人的运动过程分成两部分(应该没啥异议),然后发现两个性质:

    1.向树根跑的人,t+dep不变;

    2.向叶子跑的人,dep-t不变;

    然后用两个桶存上面两个值,dfs就行。

    代码:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define N 300005
    int n,m,hed[N],cnt;
    inline int rd()
    {
        int f=1,c=0;char ch = getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=(c<<3)+(c<<1)+ch-'0';ch=getchar();}
        return f*c;
    }
    struct EDge
    {
        int to;
        int nxt;
    }e[2*N];
    void ae(int f,int t)
    {
        e[++cnt].to=t;
        e[cnt].nxt=hed[f];
        hed[f]=cnt;
    }
    int tp[N],fa[N],dep[N],son[N],siz[N];
    void dfs0(int u)
    {
        siz[u]=1;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(to==fa[u])continue;
            fa[to]=u;
            dep[to]=dep[u]+1;
            dfs0(to);
            if(siz[to]>siz[son[u]])
            {
                son[u]=to;
            }
            siz[u]+=siz[to];
        }
    }
    void dfs1(int u,int tpp)
    {
        tp[u]=tpp;
        if(!son[u])return ;
        dfs1(son[u],tpp);
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(to==fa[u]||to==son[u])continue;
            dfs1(to,to);
        }
    }
    int get_lca(int a,int b)
    {
        while(tp[a]!=tp[b])
        {
            if(dep[tp[a]]<dep[tp[b]])swap(a,b);
            a=fa[tp[a]];
        }
        return dep[a]>dep[b]?b:a;
    }
    int w[N],ans[N];
    int dfsx[N][2],cnt1[2];//0 dep+w 1 dep-w
    struct Node
    {
        int v,delta,nxt;
    }d1[N<<1][2];
    void aN(int x,int tip,int v,int delta)
    {
        d1[++cnt1[tip]][tip].v=v;
        d1[cnt1[tip]][tip].delta=delta;
        d1[cnt1[tip]][tip].nxt=dfsx[x][tip];
        dfsx[x][tip]=cnt1[tip];
    }
    int T[N<<1][2];
    void dfs(int u)
    {
        int tmp = T[dep[u]+w[u]+N][0]+T[dep[u]-w[u]+N][1];
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(to==fa[u])continue;
            dfs(to);
        }
        for(int tp = 0;tp<=1;tp++)
        {
            for(int j=dfsx[u][tp];j;j=d1[j][tp].nxt)
            {
                T[d1[j][tp].v+N][tp]+=d1[j][tp].delta;
            }
        }
        ans[u]+=(T[dep[u]+w[u]+N][0]+T[dep[u]-w[u]+N][1])-tmp;
    } 
    int main()
    {
        n=rd(),m=rd();
        for(int f,t,i=1;i<n;i++)
        {
            f=rd(),t=rd();
            ae(f,t);
            ae(t,f);
        }
        dfs0(1);
        dfs1(1,1);
        for(int i=1;i<=n;i++)
        {
            w[i]=rd();
        }
        for(int f,t,i=1;i<=m;i++)
        {
            f=rd(),t=rd();
            int LCA = get_lca(f,t);
            if(dep[LCA]+w[LCA]==dep[f])ans[LCA]--;
            aN(f,0,dep[f],1);
            aN(fa[LCA],0,dep[f],-1);
            aN(t,1,2*dep[LCA]-dep[f],1);
            aN(fa[LCA],1,2*dep[LCA]-dep[f],-1);
        }
        dfs(1);
        for(int i=1;i<=n;i++)
        {
            printf("%d ",ans[i]);
        }
        printf("
    ");
        return 0;
    }
  • 相关阅读:
    CDQ
    MySQL中的类Decode用法
    HTMLTestRunner生成空白resault.html
    参数化时按行读取txt文件,如何去掉换行符" "
    打开本地html的一些设置
    python中文乱码例子
    Python异常处理实例
    Python根据上下限生成不重复随机数1
    Linux自定义命令
    Python IDLE 清屏工具
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9582146.html
Copyright © 2011-2022 走看看