zjoi 2007 hide 捉迷藏 动态树分治

题意:捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子。某天,Jiajia、Wind和孩子们决定在家里玩捉迷藏游戏。他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋子都互相可达。 游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯。在起初的时候,所有的灯都没有被打开。每一次,孩子们只会躲藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要求打开某个房间的电灯或者关闭某个房间的电灯。为了评估某一次游戏的复杂性,Jiajia希望知道可能的最远的两个孩子的距离(即最远的两个关灯房间的距离)。 我们将以如下形式定义每一种操作: C(hange) i 改变第i个房间的照明状态,若原来打开,则关闭;若原来关闭,则打开。 G(ame) 开始一次游戏,查询最远的两个关灯房间的距离。


思路:动态的树的分治


  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 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 f[NMAX],white_sum;
30 int n,m,top,root,ans[NMAX*2];
31 int sumsize,minsize;
32 void add(int x,int y)
33 {
34 node *p=&memo[top++];
35 p->num=y; p->next=graph[x]; graph[x]=p;
36 p=&memo[top++];
37 p->num=x; p->next=graph[y]; 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+1,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 freopen("hide.in","r",stdin);
118 freopen("hide.out","w",stdout);
119 ans[0]=-1;
120 int i,j;
121 char c[10];
122 int x,y,z;
123 scanf("%d",&n);
124 label=top=0;
125 memset(color,0,sizeof(color));
126 memset(belong,0,sizeof(belong));
127 memset(graph,0,sizeof(graph));
128 for(i=1;i<n;i++)
129 {
130 scanf("%d%d",&x,&y);
131 add(x,y);
132 }
133 top=0; white_sum=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("-1\n");
150 else if (white_sum==1) printf("0\n");
151 else printf("%d\n",ans[1]);
152 }
153 }
154 return 0;
155 }



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

导航