HDU - 3887 Counting Offspring(DFS序+主席樹)

題目鏈接

You are given a tree, it’s root is p, and the node is numbered from 1 to n. Now define f(i) as the number of nodes whose number is less than i in all the succeeding nodes of node i. Now we need to calculate f(i) for any possible i.

Input

Multiple cases (no more than 10), for each case: 
The first line contains two integers n (0<n<=10^5) and p, representing this tree has n nodes, its root is p. 
Following n-1 lines, each line has two integers, representing an edge in this tree. 
The input terminates with two zeros.

Output

For each test case, output n integer in one line representing f(1), f(2) … f(n), separated by a space.

Sample Input

15 7
7 10
7 1
7 9
7 3
7 4
10 14
14 2
14 13
9 11
9 6
6 5
6 8
3 15
3 12
0 0

Sample Output

0 0 0 0 0 1 6 0 3 1 0 0 0 2 0

題意:現在給你一棵樹,每個節點有一個編號,現在這棵樹以給出p爲根節點,問每個節點的有多少子節點編號比它小。

題解:如果在樹上處理,肯定會超時,現在我們先用DFS序將樹轉化成線性結構,用一個record數組來記錄每個節點遍歷的順序。然後每個節點的有多少子節點編號比它小,就是在record數組中兩個時間戳對應區間求該編號在區間內是第幾大,這用主席樹來維護就好了。

求大佬解釋:爲什麼一樣的代碼C++過了,但是G++MLE了?

#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<stack>
#include<string>

const int mod = 10007;
const int maxn = 1e5 + 5;
const int inf = 1e9;
const long long onf = 1e18;
#define me(a, b) memset(a,b,sizeof(a))
#define lowbit(x) x&(-x)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI 3.14159265358979323846
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int n, p;
int cnt, tot,rt, head[maxn << 1];
int in[maxn], out[maxn], record[maxn];
int root[maxn],ls[maxn*40],rs[maxn*40],sum[maxn*40];
struct node {
    int v, next;
} tree[maxn << 1];

void add_edge(int u, int v) {
    tree[cnt].v = v;
    tree[cnt].next = head[u];
    head[u] = cnt++;
}
void DFS(int u, int fa) {///DFS序
    in[u] = ++tot;
    record[tot] = u;
    for (int i = head[u]; i != -1; i = tree[i].next) {
        int v = tree[i].v;
        if (v == fa)
            continue;
        DFS(v, u);
    }
    out[u] = tot;
}
void push_date(int pre,int &node,int pos,int l,int r){
    node=++rt;
    ls[node]=ls[pre],rs[node]=rs[pre];
    sum[node]=sum[pre]+1;
    if(l==r)
        return ;
    int mid=(l+r)>>1;
    if(pos<=mid)
        push_date(ls[pre],ls[node],pos,l,mid);
    else
        push_date(rs[pre],rs[node],pos,mid+1,r);
}
int query(int pre,int node,int L,int R,int l,int r){///主席樹求第幾大
    if(L>R)
        return 0;
    if(L<=l&&R>=r)
        return sum[node]-sum[pre];
    int mid=(l+r)>>1;
    int ans=0;
    if(L<=mid)
        ans+=query(ls[pre],ls[node],L,R,l,mid);
    if(R>mid)
        ans+=query(rs[pre],rs[node],L,R,mid+1,r);
    return ans;
}
void init() {
    me(head, -1);
    tot = cnt =rt= 0;
}

int main() {
    while (scanf("%d%d", &n, &p)!=EOF){
        init();
        for (int i = 1; i < n; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            add_edge(u, v);
            add_edge(v, u);
        }
        DFS(p, -1);
        for(int i=1;i<=n;i++)
            push_date(root[i-1],root[i],record[i],1,n);///按遍歷順序建樹
        for(int i=1;i<=n;i++){
            int l=in[i],r=out[i];
            int ans=query(root[l],root[r],1,i,1,n);
            printf("%d%c",ans,i==n?'\n':' ');
        }
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章