spoj 2666 Query on a tree IV 动态树分治

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

 

思路:同zjoi 2007 hide

  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,weight;
12 node *next;
13 };
14 struct tree
15 {
16 int num,d;
17 bool w;
18 tree *next;
19 };
20 pair<int,int>child[NMAX*2];
21 priority_queue<int> Q[NMAX][2];
22 priority_queue<int> del[NMAX][2];
23 node *graph[NMAX];
24 tree *belong[NMAX];
25 tree memo_belong[50*NMAX];
26 node memo[2*NMAX];
27 bool color[NMAX];
28 int size[NMAX],label;
29 int white_sum;
30 int n,m,top,root,ans[NMAX*2];
31 int sumsize,minsize;
32 void add(int x,int y,int z)
33 {
34 node *p=&memo[top++];
35 p->num=y; p->next=graph[x]; p->weight=z;graph[x]=p;
36 p=&memo[top++];
37 p->num=x; p->next=graph[y]; p->weight=z;graph[y]=p;
38 }
39 void add_tree(int x,bool y,int d,int L)
40 {
41 tree *p=&memo_belong[top++];
42 p->num=L; p->w=y; p->next=belong[x]; p->d=d; belong[x]=p;
43 }
44 void get_root(int i,int fa)
45 {
46 int big=-1;
47 size[i]=1;
48 for(node *p=graph[i];p;p=p->next)
49 if(p->num!=fa)
50 {
51 get_root(p->num,i);
52 size[i]+=size[p->num];
53 if(size[p->num]>big) big=size[p->num];
54 }
55 if(sumsize-size[i]>big) big=sumsize-size[i];
56 if(big<minsize) minsize=big,root=i;
57 }
58 void dfs2(int i,int d,bool w,int fa,int L)
59 {
60 add_tree(i,w,d,L);
61 Q[L][w].push(d);
62 for(node *p=graph[i];p;p=p->next)
63 if(p->num!=fa)
64 dfs2(p->num,d+p->weight,w,i,L);
65 }
66 void calc(int L)
67 {
68 ans[L]=max(ans[child[L].first],ans[child[L].second]);
69 if(!Q[L][0].empty()&&!Q[L][1].empty())
70 ans[L]=max(ans[L],Q[L][0].top()+Q[L][1].top());
71 }
72 int dfs(int i,int size_i)
73 {
74 if(size_i<=2) return 0;
75 sumsize=minsize=size_i;
76 get_root(i,-1); i=root;
77 get_root(i,-1);
78 ++label;
79 int L=label;
80 node *mid,*mid_next,*p,*left=graph[i];
81 int sum=0;
82 for(p=graph[i];p->next!=NULL;p=p->next)
83 {
84 sum+=size[p->num];
85 if(sum>=(size_i-1)/2||p->next->next==NULL) break;
86 }
87 mid=p;
88 mid_next=mid->next; mid->next=NULL;
89 dfs2(i,0,0,-1,L);
90 child[L].first=dfs(i,sum+1);
91 mid->next=mid_next; graph[i]=mid_next;
92 dfs2(i,0,1,-1,L);
93 child[L].second=dfs(i,size_i-sum);
94 calc(L);
95 return L;
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]==1)
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 calc(label);
112 }
113 }
114
115 int main()
116 {
117 ans[0]=-1;
118 int i,j;
119 char c[10];
120 int x,y,z;
121 scanf("%d",&n);
122 label=top=0;
123 memset(color,0,sizeof(color));
124 memset(belong,0,sizeof(belong));
125 memset(graph,0,sizeof(graph));
126 for(i=1;i<n;i++)
127 {
128 scanf("%d%d%d",&x,&y,&z);
129 add(x,y,z);
130 }
131 white_sum=n;
132 top=0;
133 size[1]=n;
134 dfs(1,n);
135 scanf("%d",&m);
136 for(i=1;i<=m;i++)
137 {
138 scanf("%s",c);
139 if(c[0]=='C')
140 {
141 scanf("%d",&x);
142 if(color[x]==0) white_sum--;
143 else white_sum++;
144 color[x]=!color[x];
145 update(x);
146 }
147 else
148 {
149 if(white_sum==0) printf("They have disappeared.\n");
150 else if (white_sum==1)
151 printf("0\n");
152 else printf("%d\n",ans[1]);
153 }
154 }
155 return 0;
156 }

posted on 2012-03-24 17:07  myoi  阅读(1090)  评论(0编辑  收藏  举报

导航