「 HDOJ P3887 」 Counting Offspring

翻譯

題目描述

給你一棵樹,和它的樹根 $P$,而且節點從 $1\rightarrow n$ 編號,如今定義 $f(i)$ 爲 $i$ 的子樹中,節點編號小於 $i$ 的節點的個數。ios

 

輸入格式

有多組數據 (不超過 10 組),對於每組數據:
第一行兩個整數 $n,p$ $(n\le 10^5)$ 表示樹有 $n$ 個節點,樹根是 $p$。
接下來的 $n-1$ 行,每行兩個整數,表明一條樹邊。
輸入以兩個零做爲結束。測試

 

輸出格式

對於每組測試數據,輸出一行 $n$ 個整數 $f(1),f(2)......f(n)$,每兩個數字之間以一個空格分格。ui

 

解題思路

顯然,咱們想要求 $f(i)$ 的話,只須要對其子樹進行統計,而有不可以每一次都去遍歷一遍,那樣必定會超時。咱們能夠用 dfs 序先對整棵樹進行處理,dfs 序能夠將一個點的子樹的編號放在一個區間內。而後用線段樹進行求解 (若是暴力的在區間內統計的話,會 TLE,實錘),按編號從小到大將點的影響加到線段樹中,邊查詢邊更新。這樣總時間複雜度是 $\text{O}(n\log n)$,顯然可過。
要注意輸出格式,每一行最後一個數字後面不能加空格。spa

 

附上代碼

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 2e5+3;
inline int read() {
    int x = 0, f = 1; char c = getchar();
    while (c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while (c <= '9' && c >= '0') {x = x*10 + c-'0'; c = getchar();}
    return x * f;
}
int n, rt, head[maxn], Index, L[maxn], R[maxn], cnt;
struct edge {
    int nxt, to;
}ed[maxn];
inline void addedge(int x, int y) {
    ed[++cnt].nxt = head[x], ed[cnt].to = y, head[x] = cnt;
    ed[++cnt].nxt = head[y], ed[cnt].to = x, head[y] = cnt;
}
inline void dfs(int x, int fr) {
    L[x] = ++ Index;
    for(int i=head[x]; i; i=ed[i].nxt) {
        if(ed[i].to == fr) continue;
        dfs(ed[i].to, x);
    }
    R[x] = Index;
}
struct TREE {
    int l, r, sum;
}tree[maxn << 2];
struct Segment_Tree {
    #define Lson (k << 1) 
    #define Rson ((k << 1) + 1)
    inline void build(int k, int ll, int rr) {
        tree[k].l = ll, tree[k].r = rr;
        tree[k].sum = 0;
        if(tree[k].l == tree[k].r) return ;
        int mid = (tree[k].l + tree[k].r) >> 1;
        build(Lson, ll, mid);
        build(Rson, mid+1, rr);
    }
    inline void update(int k, int pos, int num) {
        if(tree[k].l == tree[k].r && tree[k].l == pos) {
            tree[k].sum += num;
            return ;
        }
        int mid = (tree[k].l + tree[k].r) >> 1;
        if(pos <= mid) update(Lson, pos, num);
        else update(Rson, pos, num);
        tree[k].sum = tree[Lson].sum + tree[Rson].sum;
    }
    inline int query(int k, int l, int r) {
        int res = 0;
        if(l <= tree[k].l && r >= tree[k].r)
            return tree[k].sum;
        int mid = (tree[k].l + tree[k].r) >> 1;
        if(l <= mid) res += query(Lson, l, r);
        if(r > mid) res += query(Rson, l, r);
        return res;
    }
}T;
int main() {
    while (scanf("%d%d", &n, &rt) == 2) {
        if(n == 0 && rt == 0) return 0;
        memset(head, 0, sizeof(head));
        cnt = 0, Index = 0;
        int x, y;
        for(int i=1; i<n; i++) {
            x = read(), y = read();
            addedge(x, y);
        }
        dfs(rt, 0);
        T.build(1, 1, n);
        for(int i=1; i<=n; i++) {
            printf("%d", T.query(1, L[i], R[i]));
            T.update(1, L[i], 1);
            if(i == n) printf("\n");
            else printf(" ");
        }
    }
}
相關文章
相關標籤/搜索