「bzoj1095」ZJOI2007 HIDE
来源:互联网 发布:外汇交易员的收入知乎 编辑:程序博客网 时间:2024/06/04 17:41
题意:给定一棵树,每个点为黑色或者白色,每次操作修改一个点或查询最远白色点对的距离。
数据范围:
首先我们考虑不修改的时候,查询最远白色点对。
我们进行点分治,维护子树内点到根的距离,对于一棵子树,我们先用max值更新答案,在用当前子树的dis值更新max,这样顺序进行,就可以保证计算出来的答案在两棵子树内,经过根节点。
静态询问一次的时间复杂度:
为了进行动态修改与查询,我们可以用这样的方法进行动态点分治:
1)建立一棵重心树,把每一层的重心链接起来形成一棵树。根据点分治的执行次数,我们可以发现这棵树的高度一定
2)我们对于每个节点记录两个堆,第一个堆维护这个子树中所有的节点到重心的距离,第二个堆记录所有子节点的一号堆的堆顶。
基于这样的两个堆,我们可以发现,第二个堆的最大和第二大加起来就是当前子树的最长链。
3)最后对于全局我们开一个堆,记录所有节点二号堆的最大值和第二大值之和,每次询问只需要取出全局的堆顶即可。
更新的细节:
加入堆只需要在分治过程中处理,用子节点的所有一号堆更新重心的二号堆,然后一号堆加上点分树的权值,就是根节点的二号堆。
因为要修改,所以堆维护的时候要涉及到删除操作,我们注意到,只需要并行维护两个优先队列,记录一个删除堆,每次取出最大值的时候,两个堆的堆顶对比,如果相同就一起删除,这样就保证删除操作是
code:
#include<bits/stdc++.h>using namespace std;using namespace std;#define rep(i,l,r) for(int i=l;i<=r;i++)#define rpp(i,x,e) for(int i=head[x];~i;i=e[i].next)#define dyes cerr<<"yes"<<endltemplate <class Type> inline void read(Type &cur){ Type ret=0,flag=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') flag=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ ret=ret*10+ch-'0'; ch=getchar(); } cur=ret*flag;}const int maxn=1e5+10;struct node{ int next,to; node(int n=0,int t=0):next(n),to(t){}}e[maxn<<1];int head[maxn],cnt;int n,m,pre[maxn],col[maxn];inline void add(int u,int v){ e[cnt]=(node){head[u],v}; head[u]=cnt++;}struct HEAP{ priority_queue<int> A,B; inline void update(){ for(;B.size()&&A.top()==B.top();A.pop(),B.pop()); } inline void push(int x){ A.push(x); } inline void pop(){ update(); A.pop(); } inline void erase(int x){ B.push(x); } inline int size(){ return A.size()-B.size(); } inline int fir(){ update(); return A.size() ? A.top():0; } inline int sec(){ if(size()<2)return 0; int x=fir();pop(); int y=fir();push(x); return y; }}ans,s1[maxn],s2[maxn];int N,root,son[maxn],size[maxn],vis[maxn];inline void getroot(int x,int f){ son[x]=0;size[x]=1; rpp(i,x,e){ if(e[i].to^f&&!vis[e[i].to]){ getroot(e[i].to,x); size[x]+=size[e[i].to]; son[x]=max(son[x],size[e[i].to]); } } son[x]=max(son[x],N-size[x]); if(son[x]<son[root]) root=x;}inline void divid(int x,int f){ pre[x]=f;vis[x]=1; rpp(i,x,e){ if(e[i].to^f&&!vis[e[i].to]){ root=0;N=size[e[i].to]; getroot(e[i].to,x); divid(root,x); } }}int fa[maxn][21],bin[21],dep[maxn];inline void init(){ bin[0]=1; rep(i,1,20) bin[i]=bin[i-1]<<1;}inline void dfs(int x){ rep(i,1,20){ if(dep[x]<bin[i]) break; fa[x][i]=fa[fa[x][i-1]][i-1]; } rpp(i,x,e){ if(e[i].to^fa[x][0]){ dep[e[i].to]=dep[x]+1; fa[e[i].to][0]=x; dfs(e[i].to); } }}inline int lca(int x,int y){ if(dep[x]<dep[y]) swap(x,y); int t=dep[x]-dep[y]; rep(i,0,20){ if(t&bin[i]) x=fa[x][i]; } for(int i=20;i>=0;i--){ if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; } if(x==y) return x; return fa[x][0];}inline int dis(int x,int y){ return dep[x]+dep[y]-(dep[lca(x,y)]<<1);}inline void turnoff(int x,int f){ if(x==f){ s2[x].push(0); if(s2[x].size()==2) ans.push(s2[x].fir()); } if(!pre[f]) return; int p=pre[f];int d=dis(x,p),tmp=s1[f].fir(); s1[f].push(d); if(d>tmp){ int mx=s2[p].fir()+s2[p].sec(); int sz=s2[p].size(); s2[p].push(d); if(tmp) s2[p].erase(tmp); int now=s2[p].fir()+s2[p].sec(); if(now>mx){ if(sz>=2) ans.erase(mx); if(s2[p].size()>=2) ans.push(now); } } turnoff(x,p);}inline void turnon(int x,int f){ if(x==f){ if(s2[x].size()==2) ans.erase(s2[x].fir()); s2[x].erase(0); } if(!pre[f]) return; int p=pre[f];int d=dis(x,p),tmp=s1[f].fir(); s1[f].erase(d); if(d==tmp){ int mx=s2[p].fir()+s2[p].sec(); int sz=s2[p].size(); s2[p].erase(d); if(s1[f].fir()) s2[p].push(s1[f].fir()); int now=s2[p].fir()+s2[p].sec(); if(now<mx){ if(sz>=2) ans.erase(mx); if(s2[p].size()>=2) ans.push(now); } } turnon(x,p);}char cmd[2];int main(int argc,const char * argv[]){ memset(head,-1,sizeof(head)); read(n); rep(i,1,n-1){ int x,y;read(x),read(y); add(x,y);add(y,x); } son[0]=0x7f7f7f7f;N=n; getroot(1,0); divid(1,0); init(); dfs(1); rep(i,1,n)s1[i].push(0),col[i]=1; rep(i,1,n)turnoff(i,i); read(m); int node=n; rep(i,1,m){ scanf("%s",&cmd); if(cmd[0]=='C'){ int x; read(x); if(!col[x]){ node++; turnoff(x,x); }else{ node--; turnon(x,x); } col[x]^=1; } if(cmd[0]=='G'){ if(node<=1) printf("%d\n",node-1); else printf("%d\n",ans.fir()); } } return 0;}
阅读全文
0 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 捉迷藏
- [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]Hide 捉迷藏(动态点分治+树上ST表)
- bzoj1095[ZJOI2007]捉迷藏
- Unix域协议
- 三种连接方式:bridge,NAT,host-only的区别
- C 语言中的指针
- Web简单文件下载
- Unix域套接字
- 「bzoj1095」ZJOI2007 HIDE
- React Native获取地理位置(获取具体城市、经纬度)
- NFS
- Error parsing XML- not well-formed (invalid token)
- 猜拳游戏(基于python面向对象3)
- 学习新浪微博计数服务
- Nuttx buttons example: undefined reference to 'poll’
- iOS圆形图片裁剪,以及原型图片外面加一个圆环
- Reactor 模式+代码讲解