spoj 2939 Query on a tree V 动态树分治

题意:给一棵树,树上的节点黑白染色,初始时全黑。每次操作可以改变一个节点的颜色,或者查到某点最近的白点距离。


  1 #include<iostream>
2 #include<cmath>
3 #include<cstdio>
4 #include<cstring>
5 #include<algorithm>
6 #include<queue>
7 using namespace std;
8 #define NMAX 100010
9 struct node
10 {
11 int num;
12 node *next;
13 };
14 struct tree
15 {
16 int num,d;
17 bool w;
18 tree *next;
19 };
20 priority_queue<int,vector<int>,greater<int> > Q[NMAX][2];
21 priority_queue<int,vector<int>,greater<int> > del[NMAX][2];
22 node *graph[NMAX];
23 tree *belong[NMAX];
24 tree memo_belong[50*NMAX];
25 node memo[2*NMAX];
26 bool color[NMAX];
27 int size[NMAX],label;
28 int n,m,top,root,ans;
29 int sumsize,minsize;
30 void add(int x,int y)
31 {
32 node *p=&memo[top++];
33 p->num=y; p->next=graph[x]; graph[x]=p;
34 p=&memo[top++];
35 p->num=x; p->next=graph[y]; graph[y]=p;
36 }
37 void add_tree(int x,bool y,int d,int L)
38 {
39 tree *p=&memo_belong[top++];
40 p->num=L; p->w=y; p->next=belong[x]; p->d=d; belong[x]=p;
41 }
42 void get_root(int i,int fa)
43 {
44 int big=-1;
45 size[i]=1;
46 for(node *p=graph[i];p;p=p->next)
47 if(p->num!=fa)
48 {
49 get_root(p->num,i);
50 size[i]+=size[p->num];
51 if(size[p->num]>big) big=size[p->num];
52 }
53 if(sumsize-size[i]>big) big=sumsize-size[i];
54 if(big<minsize) minsize=big,root=i;
55 }
56 void dfs2(int i,int d,bool w,int fa,int L)
57 {
58 add_tree(i,w,d,L);
59 for(node *p=graph[i];p;p=p->next)
60 if(p->num!=fa)
61 dfs2(p->num,d+1,w,i,L);
62 }
63 void calc(int x)
64 {
65 int label,d,w,w_rev;
66 for(tree *t=belong[x];t;t=t->next)
67 {
68 label=t->num; d=t->d; w=t->w;
69 w_rev=!w;
70 if(!Q[label][w_rev].empty())
71 ans=min(ans,Q[label][w_rev].top()+t->d);
72 }
73 }
74 void dfs(int i,int size_i)
75 {
76 if(size_i<=2) return ;
77 sumsize=minsize=size_i;
78 get_root(i,-1); i=root;
79 get_root(i,-1);
80 label++;
81 int L=label;
82 node *mid,*mid_next,*p,*left=graph[i];
83 int sum=0;
84 for(p=graph[i];p->next!=NULL;p=p->next)
85 {
86 sum+=size[p->num];
87 if(sum>=(size_i-1)/2||p->next->next==NULL) break;
88 }
89 mid=p;
90 mid_next=mid->next; mid->next=NULL;
91 dfs2(i,0,0,-1,L);
92 dfs(i,sum+1);
93 mid->next=mid_next; graph[i]=mid_next;
94 dfs2(i,0,1,-1,L);
95 dfs(i,size_i-sum);
96 }
97 void update(int x)
98 {
99 tree *t;
100 int label,d,w;
101 for(t=belong[x];t;t=t->next)
102 {
103 label=t->num; d=t->d; w=t->w;
104 if(color[x]==0)
105 del[label][w].push(d);
106 else Q[label][w].push(d);
107 while(!del[label][w].empty()&&Q[label][w].top()==del[label][w].top())
108 {
109 Q[label][w].pop(); del[label][w].pop();
110 }
111 }
112 }
113
114 int main()
115 {
116 int i,j;
117 int x,y,z;
118 scanf("%d",&n);
119 label=top=0;
120 memset(color,0,sizeof(color));
121 memset(belong,0,sizeof(belong));
122 memset(graph,0,sizeof(graph));
123 for(i=1;i<n;i++)
124 {
125 scanf("%d%d",&x,&y);
126 add(x,y);
127 }
128 top=0;
129 size[1]=n;
130 dfs(1,n);
131 scanf("%d",&m);
132 for(i=1;i<=m;i++)
133 {
134 scanf("%d",&y);
135 if(y==0)
136 {
137 scanf("%d",&x);
138 color[x]=!color[x];
139 update(x);
140 }
141 else
142 {
143 scanf("%d",&x);
144 if(color[x]==1) printf("0\n");
145 else
146 {
147 ans=NMAX;
148 calc(x);
149 if(ans==NMAX) printf("-1\n");
150 else printf("%d\n",ans);
151 }
152 }
153 }
154 return 0;
155 }



原文地址:https://www.cnblogs.com/myoi/p/2415649.html