BZOJ1095 [ZJOI2007]捉迷藏 动态点分治
来源:互联网 发布:淘宝套现可靠的店家 编辑:程序博客网 时间:2024/06/05 19:58
每次修改一个点的黑白状态,询问树上最远黑点距离
拿这个题做动态点分治模板题:(%%%PoPoQQQ大爷)
点分治的过程是对树块找重心之后分成多个小树块,降低规模分别处理的过程,把链的信息收到其中“最高重心”上,从所有的重心处像分治中的不同子树索取到重心的链,就可以覆盖所有链的信息。动态点分治就像把序列分治变成线段树一样,在分治的架子上加了信息维护,实现树链信息维护与查询。
需要什么?
每个重心需要其每个分离子树到它的信息(很重要,否则形成链的重复部分,并且还需要一个自己到自己的空信息维护单链上来的信息)
每个重心需要它到父分治块的信息
全局需要维护每个重心的信息
因此,考虑问题的静态版本,需要维护每个节点每个子树内的最长链,那么为了修改,最大化应换成堆维护。
每个重心维护一个堆,表示其分离子树中每个到它的最长链
每个重心维护一个堆,表示其块内到父重心的最长链
全局维护一个堆,表示每个重心处的最长链
修改时只要从一个节点作为重心的块开始向上修改,就可以遍历到所有包含它的块,修改到父重心的信息,修改父重心的信息
注意开始时的节点的分离子树那个堆要插一个0表示单链,而改掉节点值的时候0的存在性也要相应地变化。
堆也比较有技巧:封装双堆分别为值和删了的值,取的时候两堆顶相同则pop,相当于变种删除标记
LCA倍增写错:要返回p[x][0](QAQ)
#include<queue>#include<cstdio>#include<iostream>using namespace std;const int Mn=100005;int cnt=0,h[Mn],n,m,vst[Mn],maxx,tg,s[Mn],sz,prt[Mn];int d[Mn],p[Mn][21],co[Mn];struct Priority_Queue{priority_queue<int>q,del;void push(int x){q.push(x);}void erase(int x){del.push(x);}int top(){while(del.size()&&del.top()==q.top()) {del.pop();q.pop();}return q.top();}void Pop(){while(del.size()&&del.top()==q.top()) {del.pop();q.pop();}q.pop();}int sec_top(){int tmp=top();Pop();int se=top();push(tmp);return se;}int size(){return q.size()-del.size();}}c[Mn],f[Mn],ans;struct Edge{int to,next;}w[Mn*2];void AddEdge(int x,int y){w[++cnt]=(Edge){y,h[x]};h[x]=cnt;}void DFS(int x,int fa){ int j,y; p[x][0]=fa; for(j=1;j<=20;j++)p[x][j]=p[p[x][j-1]][j-1]; for(j=h[x];j;j=w[j].next){ y=w[j].to; if(y==fa)continue; d[y]=d[x]+1; DFS(y,x); }}void Insert(Priority_Queue &s){ if(s.size()>1)ans.push(s.top()+s.sec_top());}void Erase(Priority_Queue &s){ if(s.size()>1)ans.erase(s.top()+s.sec_top());}void init(){ int i,x,y; scanf("%d",&n); for(i=1;i<n;i++){ scanf("%d%d",&x,&y); AddEdge(x,y);AddEdge(y,x); } d[1]=1;DFS(1,0);}void DP(int x,int fa){ int j,y;s[x]=1; for(j=h[x];j;j=w[j].next){ y=w[j].to; if(y==fa||vst[y])continue; DP(y,x); s[x]+=s[y]; }}void Biggest(int x,int fa){ int j,y,mx=0; for(j=h[x];j;j=w[j].next){ y=w[j].to; if(y==fa||vst[y])continue; Biggest(y,x); mx=max(mx,s[y]); } if(maxx>max(mx,sz-s[x])){ maxx=max(mx,sz-s[x]); tg=x; }}int FindCen(int x){maxx=n+1;tg=0;DP(x,0);sz=s[x];Biggest(x,0);return tg;}int LCA(int x,int y){int j;if(d[x]<d[y])swap(x,y);for(j=20;j>=0;j--) if(d[p[x][j]]>=d[y])x=p[x][j];if(x==y)return x;for(j=20;j>=0;j--) if(p[x][j]!=p[y][j]) {x=p[x][j];y=p[y][j];}return p[x][0];}int Dis(int x,int y){return d[x]+d[y]-2*d[LCA(x,y)];}void work(int x,int fa,int Gra){ int j,y; f[Gra].push(Dis(x,prt[Gra])); for(j=h[x];j;j=w[j].next){ y=w[j].to; if(y==fa||vst[y])continue; work(y,x,Gra); }}int DivOnT(int x,int fa){int j,y,G,Gy;G=FindCen(x);prt[G]=fa;work(G,0,G);vst[G]=1;c[G].push(0);for(j=h[G];j;j=w[j].next){y=w[j].to;if(!vst[y]){Gy=DivOnT(y,G);c[G].push(f[Gy].top());}}Insert(c[G]);return G;}void Light(int x){ Erase(c[x]); c[x].erase(0); Insert(c[x]); for(int y=x;prt[y];y=prt[y]){Erase(c[prt[y]]);if(f[y].size())c[prt[y]].erase(f[y].top());f[y].erase(Dis(x,prt[y]));if(f[y].size())c[prt[y]].push(f[y].top());Insert(c[prt[y]]); }}void LiOut(int x){ Erase(c[x]); c[x].push(0); Insert(c[x]); for(int y=x;prt[y];y=prt[y]){Erase(c[prt[y]]);if(f[y].size())c[prt[y]].erase(f[y].top());f[y].push(Dis(x,prt[y]));if(f[y].size())c[prt[y]].push(f[y].top()); Insert(c[prt[y]]); }}void solve(){ int i,x;char ch[5]; cnt=n; scanf("%d",&m); for(i=1;i<=m;i++){ scanf("%s",ch); if(ch[0]=='G'){ if(cnt<=1)printf("%d\n",cnt-1); else printf("%d\n",ans.top());} else{ scanf("%d",&x); if(!co[x]){cnt--;Light(x);co[x]=1;}else{cnt++;LiOut(x);co[x]=0;}} }}int main(){ init(); DivOnT(1,0); solve();return 0;}
3 0
- BZOJ1095 [ZJOI2007]捉迷藏 动态点分治
- [动态点分治] BZOJ1095: [ZJOI2007]Hide 捉迷藏
- [bzoj1095][ZJOI2007]Hide 捉迷藏(动态点分治)
- 【BZOJ1095】[ZJOI2007]Hide 捉迷藏【动态树分治】
- [BZOJ1095][ZJOI2007]Hide捉迷藏-动态树分治
- 【BZOJ1095】捉迷藏,动态点分治
- bzoj1095: [ZJOI2007]Hide 捉迷藏(动态点分治+树上ST表)
- 括号序列 || 动态树分治 bzoj1095【ZJOI2007】Hide 捉迷藏
- bzoj1095: [ZJOI2007]Hide 捉迷藏
- BZOJ1095: [ZJOI2007]Hide 捉迷藏
- BZOJ1095: [ZJOI2007]Hide 捉迷藏
- BZOJ1095 [ZJOI2007]Hide 捉迷藏
- bzoj1095[ZJOI2007]捉迷藏
- bzoj1095 Hide 捉迷藏 动态点分治+堆 (附动态点分治详解)
- bzoj 1095: [ZJOI2007]Hide 捉迷藏 (动态点分治)
- bzoj1095:Hide 捉迷藏(动态树分治)
- BZOJ1095 Hide 捉迷藏 分治
- 【ZJOI2007】bzoj1095 捉迷藏【解法一】
- poj2230(欧拉回路模板)
- 读书笔记之 sed 篇
- 解压版mysql配置问题(环境变量和注册表)
- Java对象的深复制和浅复制
- kafka源码解析之十六生产者流程(客户端如何向topic发送数据)
- BZOJ1095 [ZJOI2007]捉迷藏 动态点分治
- HDU-1020-Encoding
- Java 中equal() 方法与==的区别以及 equals()与 hashCode()方法重写
- 图表误差线
- Java经典设计模式(3):十一种行为型模式(附实例和详解)
- [LeetCode]House Robber III
- XML
- Gensim and LDA: a quick tour
- 文章标题