http://acm.hdu.edu.cn/showproblem.php?pid=3887
【题意】
- 给定一棵树,给定这棵树的根
- 对于每个结点,统计子树中编号比他小的结点个数
- 编号从小到大一次输出
【思路】
- 从小到大处理每个结点,即统计当前结点的结果后,把当前结点插入到树状数组中
【AC】
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 const int maxn=1e5+2; 6 const int maxm=2*maxn; 7 int n,rt; 8 struct edge 9 { 10 int to; 11 int nxt; 12 }e[maxm]; 13 int head[maxn]; 14 int tot; 15 int cid; 16 int l[maxn],r[maxn]; 17 int tree[maxm]; 18 int lowbit(int x) 19 { 20 return x&(-x); 21 } 22 void add(int k,int x) 23 { 24 while(k<=cid) 25 { 26 tree[k]+=x; 27 k+=lowbit(k); 28 } 29 } 30 int query(int k) 31 { 32 int ans=0; 33 while(k) 34 { 35 ans+=tree[k]; 36 k-=lowbit(k); 37 } 38 return ans; 39 } 40 void init() 41 { 42 memset(head,-1,sizeof(head)); 43 tot=0; 44 cid=0; 45 memset(tree,0,sizeof(tree)); 46 } 47 48 void addedge(int u,int v) 49 { 50 e[tot].to=v; 51 e[tot].nxt=head[u]; 52 head[u]=tot++; 53 } 54 void dfs(int u,int pa) 55 { 56 l[u]=++cid; 57 for(int i=head[u];i!=-1;i=e[i].nxt) 58 { 59 int v=e[i].to; 60 if(v==pa) continue; 61 dfs(v,u); 62 } 63 r[u]=++cid; 64 } 65 66 67 int main() 68 { 69 while(~scanf("%d%d",&n,&rt)) 70 { 71 if(n+rt==0) break; 72 init(); 73 int u,v; 74 for(int i=1;i<=n-1;i++) 75 { 76 scanf("%d%d",&u,&v); 77 addedge(u,v); 78 addedge(v,u); 79 } 80 dfs(rt,-1); 81 for(int i=1;i<=n;i++) 82 { 83 int ans=query(r[i])-query(l[i]-1); 84 if(i==1) printf("%d",ans); 85 else printf(" %d",ans); 86 add(l[i],1); 87 } 88 puts(""); 89 } 90 return 0; 91 }
树状数组
时间: 2024-10-23 13:26:36