洛谷 P2982 [USACO10FEB]慢下来Slowing down

题目描述

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.

每天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想要知道奶牛们总共要放慢多少次速度。

输入输出格式

输入格式:

 

  • 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

 

输出格式:

 

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

 

输入输出样例

输入样例#1:
5 
1 4 
5 4 
1 3 
2 4 
4 
2 
1 
5 
3 
输出样例#1:
0 
1 
0 
2 
1 
思路:树链剖分
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define MAXN 100001
using namespace std;
int n,sz,tot;
struct nond{
    int l,r,dis,flag;
}tree[MAXN*4];
int to[MAXN*2],net[MAXN*2],head[MAXN*2];
int id[MAXN],tid[MAXN];
int dad[MAXN],top[MAXN],deep[MAXN],edge[MAXN],size[MAXN];
void add(int u,int v){
    to[++tot]=v;net[tot]=head[u];head[u]=tot;
    to[++tot]=u;net[tot]=head[v];head[v]=tot;
}
void build(int now,int l,int r){
    tree[now].l=l;
    tree[now].r=r;
    if(tree[now].l==tree[now].r){
        tree[now].dis=0;
        return ;
    }
    int mid=(tree[now].l+tree[now].r)/2;
    build(now*2,l,mid);
    build(now*2+1,mid+1,r);
}
void down(int now){
    tree[now*2].dis+=tree[now].flag;
    tree[now*2+1].dis+=tree[now].flag;
    tree[now*2].flag+=tree[now].flag;
    tree[now*2+1].flag+=tree[now].flag;
    tree[now].flag=0;
}
void change(int now,int l,int r){
    if(tree[now].l==l&&tree[now].r==r){
        tree[now].dis+=1;
        tree[now].flag+=1;
        return ;
    }
    if(tree[now].flag)    down(now);
    int mid=(tree[now].l+tree[now].r)/2;
    if(r<=mid)    change(now*2,l,r);
    else if(l>mid)    change(now*2+1,l,r);
    else{
        change(now*2,l,mid);
        change(now*2+1,mid+1,r);
    } 
}
int query(int now,int x){
    if(tree[now].l==tree[now].r)
        return tree[now].dis;
    if(tree[now].flag)    down(now);
    int mid=(tree[now].l+tree[now].r)/2;
    if(x<=mid)    query(now*2,x);
    else query(now*2+1,x);
}
void dfs(int x){
    size[x]=1;
    deep[x]=deep[dad[x]]+1;
    for(int i=head[x];i;i=net[i])
        if(to[i]!=dad[x]){
            dad[to[i]]=x;
            dfs(to[i]);
            size[x]+=size[to[i]];
        }
}
void dfs1(int x){
    int t=0;
    id[x]=++sz;
    if(!top[x])    top[x]=x;
    if(edge[x]==1&&x!=1){
        tid[x]=x;
        return ;
    }
    for(int i=head[x];i;i=net[i])
        if(dad[x]!=to[i]&&size[t]<size[to[i]])
            t=to[i];
    if(t){
        top[t]=top[x];
        dfs1(t);
        tid[x]=tid[t];
    }
    for(int i=head[x];i;i=net[i])
        if(dad[x]!=to[i]&&t!=to[i]){
            dfs1(to[i]);
            tid[x]=tid[to[i]];
        }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
        edge[x]++;
        edge[y]++;
    }
    build(1,1,n);
    dfs(1);
    dfs1(1);
    for(int i=1;i<=n;i++){
        int x;
        scanf("%d",&x);
        cout<<query(1,id[x])<<endl;
        change(1,id[x],id[tid[x]]);
    }
}
/*
5
1 4
5 4
1 3
2 4
4
2
1
5
3 
*/

 

posted @ 2017-09-05 17:56  一蓑烟雨任生平  阅读(174)  评论(0编辑  收藏  举报