P3258 [JLOI2014]新しい家の説明をリス

タイトル説明

新しい家はほんの数日前に新しい家、そこに新しい家を改装し、木のリスです\(N \)の部屋、そしてそこ(\ N-1)\ルート分岐接続、各部屋には、お互いに達することができる、との2部屋の間の経路はユニークです。神は、彼が実際に本当にに住ん「木。」

リスは、くまのプーさんを訪問する招待、また訪問者のガイドを指定するのが好き、彼は、彼のガイドラインくまのプーさん順序に従うことを行くことができるように期待している(A_1 \)\、に行く(A_2 \)\、......、最後にする(A_N \)\新しい家を訪問し、。しかし、これは部屋の多くは、くまのプーさんを繰り返して行くことになります、くまのプーさん怠惰は絶えず下落します。リスは、それぞれの部屋に行ったことを彼に告げた。しかし、彼は部屋から食べるようにキャンディを取ることができます。

プーさんは貪欲な男で、すぐに合意しました。今、リスが食べてプーさんのお菓子を確保するために知ってほしい、彼はすべての部屋に少なくともキャンディーの数を置く必要があります。

リスビジターガイドの最後の部屋ので\(A_N \)彼は豪華なごちそうを準備レストラン、で、時間は最終的にプーさんのレストランに到着したときにお菓子を食べる機会を訪問する必要はありません。

入力形式

最初の行の整数\(N- \)、2行目は部屋の数を示す(N- \)\ターンに記載整数、\(A_1-A_N \)

\(N-1 \)二つの整数の行\(X \)、\ (Y \) 数字を表す\(X \)\(Y \)を二つの部屋の間にブランチが接続されています。 。

出力フォーマット

合計\(N \)ライン、\(私は\)私は、少なくとも配置する必要がどのように多くのキャンディーの部屋のためにライン出力ラベルは、くまのプーさんを作るためにお菓子を食べなければなりません。

サンプル入力と出力

入力#1

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

出力#1

1
2
1
2
1

説明/ヒント

\(2 <= N <= 300000 \)

解像度:

LCA +ツリーの差分

数字へのアクセスは、我々は、フォーム側にそれを回します。

すべての側面については、

私たちは、最初と最後の1が特別であるでしょう。

  1. [U、V]:最初の2つのエンドポイントを、即ち、含まれる2つのエンドポイント菓子に置かれています

  2. 最後のものは2つのエンドポイントは、その2つのエンドポイント上のお菓子を保持含まれていないです:(U、V)

  3. 残りのパス後には含まれていない、フロントを含む、同じである:[U、V)

Fは、UおよびVは、エンドポイント側であり、アレイ乗算器LCAのアレイです。

  1. 特別な処理をせず、直接木を差動、最初のエッジを見てください。

  2. 最後に片側に、我々は3例の合計を議論する必要があります。

    1. u != LCA && v != LCAその後、我々は、F [U] [0] [V] -f [0]である側を差動する必要があります。
    2. u == LCA && v != LCAその後、我々は息子[U] [V] -f [0]である側を差動する必要があります。
    3. u != LCA && v == LCAその後、我々はサイドを差動する必要がF [U] [0] [V] -sonです。
  3. 残りの側面はまた、3例を議論しました:
    1. u != LCA && v != LCAその後、我々は、F [U] [0] -vある側を差動する必要があります。
    2. u == LCA && v != LCAその後、我々は側は息子[U] -vされた差動する必要があります。
    3. u != LCA && v == LCAその後、我々はサイドを差分する必要が[0] -v F [U]であります

これが完了すると、ツリーは、ボードの違いであり、ここではに入りません。

#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstdlib>
#include <vector>
#include <map>
#include <cstring>
#include <queue>
#include <stack>
#include <algorithm>
#define re register
#define gc getchar
inline int read() {
    int s = 0, f = 1; char ch = gc();
    while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = gc();}
    while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = gc();
    return s * f;
}
inline int min(int a, int b) {return a < b ? a : b;}
inline int max(int a, int b) {return a > b ? a : b;}
const int INF = 0x7fffffff;
const int Max = 600012;
const int mod = 19260817;
const int N = 1000007;
struct Candy {
    int net, to;
}t[Max];
int n, head[Max], cnt, f[Max][21];
int x[Max], y[Max], k[Max], deep[Max];
inline void insert(int u, int v) {
    t[++cnt].to = v;
    t[cnt].net = head[u];
    head[u] = cnt;
}
void dfs(int x, int Fa) {
    f[x][0] = Fa; deep[x] = deep[Fa] + 1;
    for(int i = 1; (1 << i) <= deep[x]; i++)
        f[x][i] = f[f[x][i-1]][i-1];
    int v;
    for(re int i = head[x]; i; i = t[i].net) {
        v = t[i].to;
        if(v == Fa) continue;
        dfs(v,x);
    }
}
int lca(int x, int y) {
    if(deep[x] < deep[y]) std :: swap(x, y);
    for(re int i = 21; i >= 0; -- i)
        if(deep[x] - (1 << i) >= deep[y])
            x = f[x][i];
    if(x == y) return x;
    for(re int i = 20; i >= 0; -- i)
        if(f[x][i] == f[y][i]) continue;
        else x = f[x][i], y = f[y][i];
    return f[x][0];
}
void SUM(int x, int Fa) {
    int v;
    for(re int i = head[x]; i; i = t[i].net) {
        v = t[i].to; if(v == Fa) continue;
        SUM(v, x); k[x] += k[v];
    }
}
int find_son(int x, int LCA) {
    int depth = deep[LCA] + 1;
    for(re int i = 21; i >= 0; -- i)
        if(deep[x] - (1 << i) >= depth)
            x = f[x][i];
    return x;
}
int main() {
    n = read(); int u, v; x[1] = read();
    for(re int i = 1; i < n; ++ i) y[i] = read(), x[i+1] = y[i];
    for(re int i = 1; i < n; ++ i)
        u = read(), v = read(), insert(u,v), insert(v,u);
    dfs(1,0);
    int LCA = lca(x[n-1], y[n-1]); bool fg = 1;
    if(x[n-1] != LCA && y[n-1] != LCA)
        u = f[x[n-1]][0], v = f[y[n-1]][0];
    else if(x[n-1] == LCA && y[n-1] != LCA) {
        u = find_son(y[n-1], LCA), v = f[y[n-1]][0];
        if(f[y[n-1]][0] == x[n-1]) fg = 0;
    }
    else if(x[n-1] != LCA && y[n-1] == LCA) {
        u = f[x[n-1]][0], v = find_son(x[n-1], LCA);
        if(f[x[n-1]][0] == y[n-1]) fg = 0;
    }
    LCA = lca(u, v);
    if(fg) k[u] ++, k[v] ++, k[LCA] --, k[f[LCA][0]] --;
    u = x[1]; v = y[1]; LCA = lca(u, v);
    k[u] ++, k[v] ++, k[LCA] --, k[f[LCA][0]] --;
    for(re int i = 2; i < n - 1; ++ i) {
        LCA = lca(x[i], y[i]);
        if(x[i] != LCA && y[i] != LCA)
            u = f[x[i]][0], v = y[i];
        else if(x[i] == LCA && y[i] != LCA)
            u = find_son(y[i], LCA), v = y[i];
        else if(x[i] != LCA && y[i] == LCA)
            u = f[x[i]][0], v = y[i];
        LCA = lca(u,v);
        k[u] ++, k[v] ++, k[LCA] --, k[f[LCA][0]] --;
    }
    SUM(1,0);
    for(re int i = 1; i <= n; ++ i) printf("%d\n",k[i]);
    return 0;
}

おすすめ

転載: www.cnblogs.com/ypay/p/11635371.html