BZOJ1095 [ZJOI2007]Hide 捉迷藏
动态树分治,用三个set分别维护每个重心到每一个子树的距离种类、每个重心所有子树的最大值和次大值、全局答案的最大值。复杂度O(nlogn^2)
代码
- #include<cstdio>
- #include<algorithm>
- #include<vector>
- #include<set>
- #define pb push_back
- using namespace std;
- const int N = ;
- int size[N],flag[N],n,a,b,i,f[N],cnt,typ[N],deep[N];
- int jump[N][];
- int q;
- char ch[];
- vector<int> e[N];
- multiset<int> dist[N],ans[N],Ans;
- multiset<int>::iterator it;
- int getroot(int x,int fa,int n)
- {
- int i,tmp=,rt=;
- size[x]=;
- for (i=;i<e[x].size();i++)
- if ((e[x][i]!=fa)&&(!flag[e[x][i]]))
- {
- rt|=getroot(e[x][i],x,n);
- size[x]+=size[e[x][i]];
- if (size[e[x][i]]>n/) tmp=;
- }
- if (n-size[x]>n/) tmp=;
- if (tmp==) return rt;else return x;
- }
- void gao(int x,int fa,int y,int dis)
- {
- dis++;
- int i;
- dist[y].insert(dis);
- for (i=;i<e[x].size();i++)
- if ((!flag[e[x][i]])&&(e[x][i]!=fa))
- gao(e[x][i],x,y,dis);
- }
- void DFS(int x,int fa)
- {
- int i;
- deep[x]=deep[fa]+;
- jump[x][]=fa;
- for (i=;i<=;i++)
- jump[x][i]=jump[jump[x][i-]][i-];
- for (i=;i<e[x].size();i++)
- if (e[x][i]!=fa) DFS(e[x][i],x);
- }
- int lca(int a,int b)
- {
- int i;
- if (deep[a]<deep[b]) a^=b^=a^=b;
- for (i=;i>=;i--)
- if (deep[jump[a][i]]>=deep[b]) a=jump[a][i];
- if (a==b) return a;
- for (i=;i>=;i--)
- if (jump[a][i]!=jump[b][i]) a=jump[a][i],b=jump[b][i];
- return jump[a][];
- }
- int getdis(int x,int y)
- {
- int z=lca(x,y);
- return deep[x]+deep[y]-*deep[z];
- }
- void del(int x)
- {
- int tmp=;
- if (ans[x].size()>=)
- {
- it=ans[x].end();
- --it;tmp+=*it;
- --it;tmp+=*it;
- it=Ans.lower_bound(tmp);
- Ans.erase(it);
- }
- }
- void ins(int x)
- {
- int tmp=;
- if (ans[x].size()>=)
- {
- it=ans[x].end();
- --it;tmp+=*it;
- --it;tmp+=*it;
- Ans.insert(tmp);
- }
- }
- void DEL(int y)
- {
- if (dist[y].size())
- {
- it=dist[y].end();--it;
- int tmp=*it;
- it=ans[f[y]].lower_bound(tmp);
- ans[f[y]].erase(it);
- }
- }
- void INS(int y)
- {
- if (dist[y].size())
- {
- it=dist[y].end();--it;
- int tmp=*it;
- ans[f[y]].insert(tmp);
- }
- }
- int change(int x,int y)
- {
- del(x);
- if (typ[x]==)
- {
- it=ans[x].lower_bound();
- ans[x].erase(it);
- }
- else
- ans[x].insert();
- while (x)
- {
- ins(x);
- if (f[x])
- {
- del(f[x]);
- DEL(x);
- int dis=getdis(f[x],y);
- if (typ[y]==)
- {
- it=dist[x].lower_bound(dis);
- dist[x].erase(it);
- }
- else
- dist[x].insert(dis);
- INS(x);
- }
- x=f[x];
- }
- }
- int dfs(int x,int n,int fa)
- {
- int i,y;
- x=getroot(x,,n);
- f[x]=fa;
- flag[x]=;
- ans[x].insert();
- for (i=;i<e[x].size();i++)
- if (!flag[e[x][i]])
- {
- if (size[e[x][i]]>size[x])
- y=dfs(e[x][i],n-size[x],x);
- else
- y=dfs(e[x][i],size[e[x][i]],x);
- gao(e[x][i],,y,);
- it=dist[y].end();
- ans[x].insert(*(--it));
- }
- ins(x);
- flag[x]=;
- return x;
- }
- int main()
- {
- scanf("%d",&n);
- for (i=;i<n;i++)
- {
- scanf("%d%d",&a,&b);
- e[a].pb(b);
- e[b].pb(a);
- }
- dfs(,n,);
- DFS(,);
- scanf("%d",&q);
- for (i=;i<=q;i++)
- {
- scanf("%s",ch+);
- if (ch[]=='G')
- {
- if (cnt==n)
- printf("-1\n");
- else
- if (cnt==n-)
- printf("0\n");
- else
- {
- it=Ans.end();--it;
- printf("%d\n",*it);
- }
- }
- else
- if (ch[]=='C')
- {
- scanf("%d",&a);
- if (typ[a]==)
- cnt++,typ[a]=;
- else
- cnt--,typ[a]=;
- change(a,a);
- }
- }
- }
BZOJ1095 [ZJOI2007]Hide 捉迷藏的更多相关文章
- 动态点分治:Bzoj1095: [ZJOI2007]Hide 捉迷藏
简介 这是我自己的一点理解,可能写的不好 点分治都学过吧.. 点分治每次找重心把树重新按重心的深度重建成了一棵新的树,称为分治树 这个树最多有log层... 动态点分治:记录下每个重心的上一层重心,这 ...
- [bzoj1095][ZJOI2007]Hide 捉迷藏 点分树,动态点分治
[bzoj1095][ZJOI2007]Hide 捉迷藏 2015年4月20日7,8876 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiaji ...
- BZOJ1095:[ZJOI2007]Hide 捉迷藏(动态点分治)
Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩 捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条 ...
- BZOJ1095: [ZJOI2007]Hide 捉迷藏【线段树维护括号序列】【思维好题】
Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩 捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条 ...
- BZOJ1095: [ZJOI2007]Hide 捉迷藏【动态点分治】
Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩 捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条 ...
- bzoj千题计划245:bzoj1095: [ZJOI2007]Hide 捉迷藏
http://www.lydsy.com/JudgeOnline/problem.php?id=1095 查询最远点对,带修改 显然可以用动态点分治 对于每个点,维护两个堆 堆q1[x] 维护 点分树 ...
- BZOJ1095 [ZJOI2007]Hide 捉迷藏 动态点分治 堆
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ1095.html 题目传送门 - BZOJ1095 题意 有 N 个点,每一个点是黑色或者白色,一开始所 ...
- BZOJ1095 [ZJOI2007]Hide 捉迷藏 【动态点分治 + 堆】
题目链接 BZOJ1095 题解 传说中的动态点分治,一直不敢碰 今日一会,感觉其实并不艰涩难懂 考虑没有修改,如果不用树形dp的话,就得点分治 对于每个重心,我们会考虑其分治的子树内所有点到它的距离 ...
- bzoj1095: [ZJOI2007]Hide 捉迷藏 线段树维护括号序列 点分治 链分治
这题真是十分难写啊 不管是点分治还是括号序列都有一堆细节.. 点分治:时空复杂度$O(n\log^2n)$,常数巨大 主要就是3个堆的初始状态 C堆:每个节点一个,为子树中的点到它父亲的距离的堆. B ...
随机推荐
- BC一周年练习赛
Souvenir Accepts: 901 Submissions: 2743 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262 ...
- XVI Open Cup named after E.V. Pankratiev. GP of SPB
A. Bubbles 枚举两个点,求出垂直平分线与$x$轴的交点,答案=交点数+1. 时间复杂度$O(n^2\log n)$. #include<cstdio> #include<a ...
- BZOJ 2431 & DP
题意:求逆序对数量为k的长度为n的排列的个数 SOL: 显然我们可以对最后一位数字进行讨论,判断其已经产生多少逆序对数量,然后对于前n-1位同样考虑---->每一个长度的排列我们都可以看做是相同 ...
- CSS:在IE浏览器下,元素下沉一行的解决办法
HTML: <ul> <li><a href="">嘻嘻嘻嘻嘻嘻</a><span>2015-12-17</spa ...
- javascript继承机制的设计思想(ryf)
我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类"的概念,也没有"类"(class)和"实例" ...
- Codeforces Round #371 (Div. 2) C
传送门 map或者字典数的应用 简单题 题意: 思路: AC代码: #include<iostream> #include<cstring> #include<cmat ...
- [LintCode] Min Stack 最小栈
Implement a stack with min() function, which will return the smallest number in the stack. It should ...
- npm link 安装本地模块,将本地模块cli化
第三方学习地址 http://mp.weixin.qq.com/s?__biz=MzAxMTU0NTc4Nw==&mid=2661157390&idx=1&sn=6d96e54 ...
- Android课程---添加黑名单的练习2(课堂讲解)
实现黑名单的添加.修改.查询和删除,首先得有封装的3个类,便于使用 BlackNumber.java package com.hanqi.test3; /** * Created by Adminis ...
- 骑士游历/knight tour - visual basic 解决
在visual baisc 6 how to program 中文版第七章的练习题上看到了这个问题,骑士游历的问题. 在8x8的国际象棋的棋盘上,骑士(走法:一个方向走两格,另一个方向一格)不重复走完 ...