bzoj1095: [ZJOI2007]Hide 捉迷藏
来源:互联网 发布:c语言打印糖果图形 编辑:程序博客网 时间:2024/05/22 10:24
题目链接
bzoj1095
题意
Description
捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子。某天,Jiajia、Wind和孩子们决定在家里玩捉迷藏游戏。他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋子都互相可达。游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯。在起初的时候,所有的灯都没有被打开。每一次,孩子们只会躲藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要求打开某个房间的电灯或者关闭某个房间的电灯。为了评估某一次游戏的复杂性,Jiajia希望知道可能的最远的两个孩子的距离(即最远的两个关灯房间的距离)。 我们将以如下形式定义每一种操作: C(hange) i 改变第i个房间的照明状态,若原来打开,则关闭;若原来关闭,则打开。 G(ame) 开始一次游戏,查询最远的两个关灯房间的距离。
Input
第一行包含一个整数N,表示房间的个数,房间将被编号为1,2,3…N的整数。接下来N-1行每行两个整数a, b,表示房间a与房间b之间有一条走廊相连。接下来一行包含一个整数Q,表示操作次数。接着Q行,每行一个操作,如上文所示。
Output
对于每一个操作Game,输出一个非负整数到hide.out,表示最远的两个关灯房间的距离。若只有一个房间是关着灯的,输出0;若所有房间的灯都开着,输出-1。
Sample Input
8
1 2
2 3
3 4
3 5
3 6
6 7
6 8
7
G
C 1
G
C 2
G
C 1
G
Sample Output
4
3
3
4
HINT
对于100%的数据, N ≤100000, M ≤500000。
题解
和qtree4差不多。可以用链分治,点分治或边分治。但要支持动态修改。所以就叫动态树分治。
这里介绍一下动态的点分治。就是堆套堆套堆。(边分就是堆套堆,链分就是堆套线段树)。
我们对于一个重心,将每个子树中的点到该子树的距离都存在一个堆中,记为s1。我们可以将这个堆记录在下一层的分治重心中。然后对于每个重心在记录一个堆,插入所有子树的s1中的top,记为s2。再将s2中的第一大和第二大相加,就是经过该重心的最长链,将它存在一个答案堆中。每次询问只要输出答案堆的堆顶。对于关灯就是插点,开灯就是删点。维护一下每一层的s1和s2还有答案堆就好了。
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cmath>#include<queue>#include<vector>using namespace std;#define N 100010struct Heap{ priority_queue<int>A,B; void Push(int x){A.push(x);} void Erase(int x){B.push(x);} void Pop(){while(B.size()&&A.top()==B.top()) A.pop(),B.pop();A.pop();} int Top(){while(B.size()&&A.top()==B.top()) A.pop(),B.pop();return A.top();} int S_top(){int tmp=Top(); Pop();int ans=Top(); Push(tmp);return ans;} int Size(){return A.size()-B.size();}}s1[N],s2[N],ans;struct edge{ int x,next;}e[N*2];int first[N],tot,dis[N][20],dep[N],size[N],root,f[N],n,m,x,y,cnt;char op;bool v[N],b[N];void add(int x,int y){ e[++tot].x=y; e[tot].next=first[x]; first[x]=tot;}void dfs(int x,int y,int s){ size[x]=1; bool b=true; for(int i=first[x];i;i=e[i].next) if(!v[e[i].x]&&e[i].x!=y){ dfs(e[i].x,x,s); size[x]+=size[e[i].x]; if(size[e[i].x]>s/2) b=false; } if(s-size[x]>s/2) b=false; if(b) root=x;}void calc(int x,int y,int d,int id,Heap &s){ s.Push(d); size[x]=1; dis[x][id]=d; for(int i=first[x];i;i=e[i].next) if(e[i].x!=y&&!v[e[i].x]){ calc(e[i].x,x,d+1,id,s); size[x]+=size[e[i].x]; }}int divise(int x,int y,int s){ dfs(x,0,s); int rt=root; v[rt]=true; dep[rt]=dep[y]+1; f[rt]=y; s2[rt].Push(0); v[rt]=true; for(int i=first[rt];i;i=e[i].next) if(!v[e[i].x]){ Heap tmp; calc(e[i].x,0,0,dep[rt]+1,tmp); int rec=divise(e[i].x,rt,size[e[i].x]); s1[rec]=tmp; if(tmp.Size())s2[rt].Push(tmp.Top()+1); } if(s2[rt].Size()>1) ans.Push(s2[rt].Top()+s2[rt].S_top()); return rt; }void change(int x,int k){ if(s2[x].Size()>1)ans.Erase(s2[x].Top()+s2[x].S_top()); if(k==0) s2[x].Erase(0); else s2[x].Push(0); if(s2[x].Size()>1)ans.Push(s2[x].Top()+s2[x].S_top()); for(int i=x;f[i];i=f[i]){ if(s2[f[i]].Size()>1) ans.Erase(s2[f[i]].Top()+s2[f[i]].S_top()); if(s1[i].Size())s2[f[i]].Erase(s1[i].Top()+1); if(k==0)s1[i].Erase(dis[x][dep[i]]); else s1[i].Push(dis[x][dep[i]]); if(s1[i].Size()) s2[f[i]].Push(s1[i].Top()+1); if(s2[f[i]].Size()>1) ans.Push(s2[f[i]].Top()+s2[f[i]].S_top()); }}char BUF[200001],*buf,*end;#define getch() (buf==end?fread(BUF,1,200000,stdin),buf=BUF,end=buf+200000,*(buf++):*(buf++))inline void read(int &x){ static char c; for(c=getch();c<'0'||c>'9';c=getch()); for(x=0;'0'<=c&&c<='9';c=getch())x=x*10+c-'0';}int main(){ read(n); cnt=n; for(int i=1;i<n;i++){ read(x); read(y); add(x,y); add(y,x); } divise(1,0,n); read(m); for(int i=1;i<=m;i++){ for(op=getch();op!='C'&&op!='G';op=getch()); if(op=='G') { if(cnt>1) printf("%d\n",ans.Top()); else if(cnt==0) puts("-1"); else puts("0"); } else { read(x); if(b[x]) cnt++,b[x]=false,change(x,1); else cnt--,b[x]=true,change(x,0); } } return 0;}
- bzoj1095: [ZJOI2007]Hide 捉迷藏
- BZOJ1095: [ZJOI2007]Hide 捉迷藏
- BZOJ1095: [ZJOI2007]Hide 捉迷藏
- BZOJ1095 [ZJOI2007]Hide 捉迷藏
- [BZOJ1095][ZJOI2007][线段树]Hide捉迷藏
- 【BZOJ1095】[ZJOI2007]Hide 捉迷藏【动态树分治】
- [动态点分治] BZOJ1095: [ZJOI2007]Hide 捉迷藏
- [BZOJ1095][ZJOI2007]Hide捉迷藏-动态树分治
- 括号序列 || 动态树分治 bzoj1095【ZJOI2007】Hide 捉迷藏
- spoj2666 Qtree4(类似于bzoj1095: [ZJOI2007]Hide 捉迷藏)详解
- spoj2666 Qtree4(类似于bzoj1095: [ZJOI2007]Hide 捉迷藏)详解
- spoj2666 Qtree4(类似于bzoj1095: [ZJOI2007]Hide 捉迷藏)详解
- [bzoj1095][ZJOI2007]Hide 捉迷藏(动态点分治)
- 「BZOJ1095」「ZJOI2007」Hide 捉迷藏
- bzoj1095[ZJOI2007]捉迷藏
- BZOJ1095 Hide 捉迷藏 分治
- 【ZJOI2007】bzoj1095 捉迷藏【解法一】
- 【ZJOI2007】bzoj1095 捉迷藏【解法二】
- Could not load the FreeMarker template named 'select'
- BZOJ3571[HNOI2014]画框
- java (字符串)
- 1044 Shopping in Mars
- JavaScript构造函数模式+prototype(原型)模式拓展系统类和自定义类
- bzoj1095: [ZJOI2007]Hide 捉迷藏
- struts ValueStack 详解
- 最小与最大值
- java里面的标签运用 continue label, break label
- 【ural1297】Palindrome 后缀数组
- linux shell(1)
- vs2008单元测试
- POJ2362 Square(dfs)
- lisp资源