zoukankan      html  css  js  c++  java
  • USACO Slowing down

    洛谷 P2982 [USACO10FEB]慢下来Slowing down

    洛谷传送门

    JDOJ 2684: USACO 2010 Feb Gold 3.Slowing down

    JDOJ传送门

    Description

    Every day each of Farmer John's N (1 <= N <= 100,000) cows conveniently
    numbered 1..N move from the barn to her private pasture. The pastures
    are organized as a tree, with the barn being on pasture 1. Exactly
    N-1 cow unidirectional paths connect the pastures; directly connected
    pastures have exactly one path. Path i connects pastures A_i and
    B_i (1 <= A_i <= N; 1 <= B_i <= N).

    Cow i has a private pasture P_i (1 <= P_i <= N). The barn's small
    door lets only one cow exit at a time; and the patient cows wait
    until their predecessor arrives at her private pasture. First cow
    1 exits and moves to pasture P_1. Then cow 2 exits and goes to
    pasture P_2, and so on.

    While cow i walks to P_i she might or might not pass through a
    pasture that already contains an eating cow. When a cow is present
    in a pasture, cow i walks slower than usual to prevent annoying her
    friend.

    Consider the following pasture network, where the number between
    parentheses indicates the pastures' owner.

            1 (3)        
           / 
      (1) 4   3 (5)
         /    
    (2) 2   5 (4)
    

    First, cow 1 walks to her pasture:

            1 (3)        
           / 
      [1] 4*  3 (5)
         /    
    (2) 2   5 (4)
    

    When cow 2 moves to her pasture, she first passes into the barn's
    pasture, pasture 1. Then she sneaks around cow 1 in pasture 4 before
    arriving at her own pasture.

            1 (3)
           / 
      [1] 4*  3 (5)
         /    
    [2] 2*  5 (4)
    

    Cow 3 doesn't get far at all -- she lounges in the barn's pasture, #1.

            1* [3]
           / 
      [1] 4*  3 (5)
         /    
    [2] 2*  5 (4)
    

    Cow 4 must slow for pasture 1 and 4 on her way to pasture 5:

            1* [3]
           / 
      [1] 4*  3 (5)
         /    
    [2] 2*  5* [4]
    

    Cow 5 slows for cow 3 in pasture 1 and then enters her own private pasture:

            1* [3]
           / 
      [1] 4*  3*[5]
         /    
    [2] 2*  5* [4]
    

    FJ would like to know how many times each cow has to slow down.

    Input

    * Line 1: Line 1 contains a single integer: N

    * Lines 2..N: Line i+1 contains two space-separated integers: A_i and B_i

    * Lines N+1..N+N: line N+i contains a single integer: P_i

    Output

    * Lines 1..N: Line i contains the number of times cow i has to slow down.

    Sample Input

    5 1 4 5 4 1 3 2 4 4 2 1 5 3

    Sample Output

    0 1 0 2 1

    题目翻译

    每天Farmer John的N头奶牛(1 <= N <= 100000,编号1…N)从粮仓走向他的自己的牧场。牧场构成了一棵树,粮仓在1号牧场。恰好有N-1条道路直接连接着牧场,使得牧场之间都恰好有一条路径相连。第i条路连接着A_i,B_i,(1 <= A_i <= N; 1 <= B_i <= N)。 奶牛们每人有一个私人牧场P_i (1 <= P_i <= N)。粮仓的门每次只能让一只奶牛离开。耐心的奶牛们会等到他们的前面的朋友们到达了自己的私人牧场后才离开。首先奶牛1离开,前往P_1;然后是奶牛2,以此类推。

    当奶牛i走向牧场P_i时候,他可能会经过正在吃草的同伴旁。当路过已经有奶牛的牧场时,奶牛i会放慢自己的速度,防止打扰他的朋友。

    FJ想要知道奶牛们总共要放慢多少次速度。

    题解:

    dfs+树状数组。

    题目大意:

    在一棵树上,每个节点有点权,求每个节点的所有祖先中点权小于该节点的个数。

    那么我们凭什么得出这个题目大意呢?这棵树的节点点权是啥啊?

    很简单,通过读题可以发现这个点权其实可以算作奶牛到目标牧场的一个映射。每个点的点权就是它的奶牛的编号。这样一来题目大意就比较好理解了,这也是我们继续向下做题的基础。

    然后我们考虑DFS,DFS的时候传两个参数,节点编号和其父亲节点。我们令1号节点(根节点)的父亲节点等于0。当然,你想令其得负的也可以。

    我们一边搜索一边统计,因为我们深搜的时候节点遍历是有序的,所以我们每次搜索先向下查询再向上修改,就可以统计得出我们的答案。

    这里要注意,因为我们存的是双向边,所以我们深搜的时候应该特判不要让它跑回去。

    代码如下:

    #include<cstdio>
    using namespace std;
    int n,c[100001],p[100001],ans[100001];
    int tot,to[200001],nxt[200001],head[100001];
    void add(int x,int y)
    {
        to[++tot]=y;
        nxt[tot]=head[x];
        head[x]=tot;
    }
    void fix(int x,int k)
    {
        for(int i=x;i<=n;i+=i&-i)
            c[i]+=k;
    }
    int getsum(int x)
    {
        int ret=0;
        for(int i=x;i;i-=i&-i)
            ret+=c[i];
        return ret;
    }
    void dfs(int x,int fa)
    {
        ans[p[x]]=getsum(p[x]);
        fix(p[x],1);
        for(int i=head[x];i;i=nxt[i])
        {
            if(to[i]==fa)
                continue;
            dfs(to[i],x);
        }
        fix(p[x],-1);
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
        }
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            p[x]=i;
        }
        dfs(1,0);
        for(int i=1;i<=n;i++)
            printf("%d
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    [工具推荐]005.Axure RP Pro 7.0模拟C#TAB控件
    [安卓基础] 008.Android中的显示单位
    [JavaWeb基础] 008.Spring初步配置
    [批处理教程之Shell]002.Linux 常用命令大全
    [注]新手学习编程的最佳方式是什么?
    [C#打包部署教程]001.VS2012 + InstallShield
    [站点推荐]001.学习新技能的37个最佳网站(The 37 Best Websites To Learn Something New)
    程序员如何像写代码一样找女朋友
    [工具-006] C#如何模拟发包登录
    [Linux系统] (1)常用操作(CentOS 7.x)
  • 原文地址:https://www.cnblogs.com/fusiwei/p/11286597.html
Copyright © 2011-2022 走看看