思路:
(1):dfs对每个点标号。记录每个点的开始时间S和结束时间E.
(2):按顺序一次查询并访问每个结点。
(3):查询并访问:
for(i=1;i<=N;i++) { f[i]=Query(1,S1[i],E1[i]); Update(1,S1[i]); }
注意:要数组模拟堆栈,不然会RE。
CODE:
/*DFS标号+线段树O(N*logN)*/ /*AC代码:859ms*/ #include <iostream> #include <cstdio> #include <memory.h> #include <algorithm> #define MAXN 200000 #define INF 1e8 #define lch(a) (a<<1) #define rch(a) (a<<1|1) #define min(a,b) (a<b?a:b) #define max(a,b) (a>b?a:b) using namespace std; struct edge { int u,v,next; }E[MAXN]; int head[MAXN],ecnt; struct Tree { int s,e,num; }Tnode[2*MAXN]; int S1[MAXN],E1[MAXN]; int f[MAXN],cur[MAXN]; int Stack[10000000]; bool vis[MAXN]; int N,P,top,cnt,num; void Insert(int u,int v) { E[ecnt].u=u; E[ecnt].v=v; E[ecnt].next=head[u]; head[u]=ecnt++; } void Init() { int i,u,v; memset(head,-1,sizeof(head));ecnt=0; for(i=1;i<N;i++) { scanf("%d%d",&u,&v); Insert(u,v); Insert(v,u); } } void Build(int p,int s,int e) { Tnode[p].s=s;Tnode[p].e=e;Tnode[p].num=0; if(s==e) return; int mid=(s+e)>>1; Build(lch(p),s,mid); Build(rch(p),mid+1,e); } void Update(int p,int k) { Tnode[p].num++; if(Tnode[p].s==Tnode[p].e) return; int mid=(Tnode[p].s+Tnode[p].e)>>1; if(k<=mid) Update(lch(p),k); else Update(rch(p),k); } int Query(int p,int s,int e) { if(Tnode[p].s==s&&Tnode[p].e==e) return Tnode[p].num; int mid=(Tnode[p].s+Tnode[p].e)>>1; if(e<=mid) return Query(lch(p),s,e); else if(s>mid) return Query(rch(p),s,e); else return Query(lch(p),s,mid)+Query(rch(p),mid+1,e); } void dfs() { int i,u,v; memset(vis,false,sizeof(vis)); for(i=1;i<=N;i++) cur[i]=head[i]; top=num=0; Stack[++top]=P; while(top) { //printf("*\n"); u=Stack[top]; if(!vis[u]) { S1[u]=++num; vis[u]=true; } for(;cur[u]!=-1;cur[u]=E[cur[u]].next) { v=E[cur[u]].v; if(vis[v]) continue; Stack[++top]=v; break; } //printf("*%d %d\n",Stack[top],u); if(Stack[top]==u) { E1[u]=++num; top--; } } } void Solve() { int u,v,i; dfs(); memset(f,0,sizeof(f)); Build(1,1,2*N); for(i=1;i<=N;i++) { f[i]=Query(1,S1[i],E1[i]); //f[i]/=2; Update(1,S1[i]); //Update(1,E1[i]); } for(i=1;i<N;i++) printf("%d ",f[i]); printf("%d\n",f[i]); } int main() { while(scanf("%d%d",&N,&P)!=EOF) { if(N==0&&P==0) break; Init(); Solve(); } return 0; }