题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3887
这个题目和 poj3321 apple-tree 属于同一类型的题目
题目大意:求树的叶子中比根的数字小的数 的个数
思路:可以在http://blog.csdn.net/zssee33/article/details/7927286上面看
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1 | 1
#define mid int m = (l+r) >> 1
struct Edge
{
int v, next;
}edge[232323];
int head[200000];
int vis[200000];
int l[200000], r[200000];
int cnt[800000];
stack <int> st;
int tot ;
void add_edge(int s, int v)
{
edge[tot].v = v ;
edge[tot].next = head[s];
head[s] = tot ++;
}
void dfs(int rt)
{
st.push(rt);
memset(vis, 0, sizeof(vis));
while(!st.empty())
{
int u = st.top();
// printf("u = %d\n", u);
if(!vis[u])
{
vis[u] = 1;
l[u] = tot ++;
}
int i;
int flag = 0;
for(i = head[u]; i != -1; i = edge[i].next)
{
int e = edge[i].v ;
if(!vis[e])
{
flag = 1;
st.push(e);
head[u] = edge[i].next ;
break;
}
}
if(flag)
continue ;
if(vis[u])
{
r[u] = tot ++;
st.pop();
}
}
}
void update(int d, int l, int r, int rt)
{
if(l == r)
{
cnt[rt] = 1;
return ;
}
mid ;
if(d <= m)
update(d, lson);
else update(d, rson);
cnt[rt] = cnt[rt << 1] + cnt[rt <<1 | 1];
}
int query(int L, int R, int l, int r, int rt)
{
if(L <= l && r <= R)
{
return cnt[rt];
}
int ret = 0;
mid ;
if(L <= m)
ret += query(L, R, lson);
if(m < R)
ret += query(L, R, rson);
return ret ;
}
int main()
{
int n, m;
while(scanf("%d%d", &n, &m) != EOF)
{
if(!n && !m)
break;
memset(cnt, 0, sizeof(cnt));
tot = 0;
int a, b, i;
memset(head, -1, sizeof(head));
for(i = 0; i < n-1; i ++)
{
scanf("%d%d", &a, &b);
add_edge(a, b);
add_edge(b, a);
}
tot = 1;
dfs(m);
for(i = 1; i < n; i ++)
{
int k = query(l[i], r[i], 1, tot, 1);
printf("%d ", k);
update(l[i], 1, tot, 1);
}
printf("%d\n", query(l[i], r[i], 1, tot, 1));
}
return 0;
}