POJ 3321 Apple Tree(树状数组)
很不错的一个题,开始搞了一个裸树的,后来听宝哥说用DFS把一个节点给离散成一段区间,重新标号,想了一下,好久没敲树状数组了,敲完发现还是TLE,比较发现我用左儿子,右兄弟的建树好像效率很低啊,改成链表形式的邻接表存图,终于过了。
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 int p[200001],str[200001],end[200001],n,num; 5 struct node//挂链的邻接表 6 { 7 int data; 8 struct node *next; 9 }*tree[200001],*temp; 10 int lowbit(int t) 11 { 12 return t&(-t); 13 } 14 void instert(int t,int d) 15 { 16 while(t <= n) 17 { 18 p[t] += d; 19 t += lowbit(t); 20 } 21 } 22 int getsum(int t) 23 { 24 int sum = 0; 25 while(t > 0) 26 { 27 sum += p[t]; 28 t -= lowbit(t); 29 } 30 return sum; 31 } 32 void build(int father,int son)//建树 33 { 34 temp = new node; 35 temp -> data = son; 36 temp -> next = NULL; 37 temp -> next = tree[father]; 38 tree[father] = temp; 39 } 40 void dfs(int x) 41 { 42 if(x == 0) return; 43 str[x] = num ++; 44 node *t; 45 t = tree[x]; 46 while(t) 47 { 48 dfs(t->data); 49 t = t -> next; 50 } 51 end[x] = num-1; 52 } 53 int main() 54 { 55 int i,m,fa,son,key; 56 char ch; 57 while(scanf("%d",&n)!=EOF) 58 { 59 memset(p,0,sizeof(p)); 60 for(i = 1; i <= n-1; i ++) 61 { 62 scanf("%d%d",&fa,&son); 63 build(fa,son); 64 } 65 num = 1; 66 dfs(1); 67 for(i = 1; i <= n; i ++) 68 { 69 instert(i,1);//初始化 70 } 71 scanf("%d%*c",&m); 72 for(i = 1; i <= m; i ++) 73 { 74 scanf("%c%d%*c",&ch,&key); 75 if(ch == 'Q') 76 printf("%d\n",getsum(end[key])-getsum(str[key]-1)); 77 else 78 { 79 if(getsum(str[key]) - getsum(str[key]-1) == 1)//其实这里理解错题意了,就是简单的单点更新。。。 80 instert(str[key],-1); 81 else 82 instert(str[key],1); 83 } 84 } 85 } 86 return 0; 87 }