BZOJ1095: [ZJOI2007]Hide 捉迷藏
2017-03-30 09:22
381 查看
所以为什么这道是动态点分治的模板题….细节好爆炸
动态点分治按每次分治的重心建树,然后在分治的过程中处理出每个点在原树中到它新树中log个父亲的距离,它在新树中的层数
然后维护(好多个)堆,分别是(新树中)每个点的子树内所有点到它父亲的距离heap[x],(新树中)每个点各个子树到它的最长链heap2[x](注意自己到自己的一条长度为0的链以处理子树延伸上来的单链),还有一个全局的堆维护每个重心处的答案(他的子树内经过他的最长链,即取出最长的两条不同子树到它的最长链)
code:
动态点分治按每次分治的重心建树,然后在分治的过程中处理出每个点在原树中到它新树中log个父亲的距离,它在新树中的层数
然后维护(好多个)堆,分别是(新树中)每个点的子树内所有点到它父亲的距离heap[x],(新树中)每个点各个子树到它的最长链heap2[x](注意自己到自己的一条长度为0的链以处理子树延伸上来的单链),还有一个全局的堆维护每个重心处的答案(他的子树内经过他的最长链,即取出最长的两条不同子树到它的最长链)
code:
#include<set> #include<map> #include<deque> #include<queue> #include<stack> #include<cmath> #include<ctime> #include<bitset> #include<string> #include<vector> #include<cstdio> #include<cstdlib> #include<cstring> #include<climits> #include<complex> #include<iostream> #include<algorithm> #define ll long long using namespace std; inline void up(int &x,const int &y){if(x<y)x=y;} inline void read(int &x) { char c; while(!((c=getchar())>='0'&&c<='9')); x=c-'0'; while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0'; } const int maxn = 101000; const int maxd = 20; int n,m; struct edge { int y,nex; edge(){} edge(const int _y,const int _nex){y=_y;nex=_nex;} }a[maxn<<1]; int len,fir[maxn]; inline void ins(const int x,const int y){a[++len]=edge(y,fir[x]);fir[x]=len;} bool light[maxn]; int countl; struct node { int x,i,ti; node(){} node(const int _x,const int _i,const int _ti){x=_x;i=_i;ti=_ti;} }; inline bool operator <(node x,node y){return x.x<y.x;} priority_queue<node>heap[maxn],heap2[maxn],Ans; // 到fa距离 son到x距离max int th2[maxn]; int ans[maxn]; int fa[maxn],dis[maxn][maxd]; int siz[maxn]; int dep[maxn]; void find_root(const int x,const int ff,const int num,const int lasdep,int &root) { int maxs=0; siz[x]=1; for(int k=fir[x];k;k=a[k].nex) { const int y=a[k].y; if(!dep[y]&&y!=ff) { dis[y][lasdep]=dis[x][lasdep]+1; find_root(y,x,num,lasdep,root); up(maxs,siz[y]); siz[x]+=siz[y]; } } if(maxs*2<=num&&(num-siz[x])*2<=num) root=x; } void upd(const int x,const int ff,const int root) { heap[root].push(node(dis[x][dep[root]-1],x,0)); for(int k=fir[x];k;k=a[k].nex) { const int y=a[k].y; if(y!=ff&&!dep[y]) upd(y,x,root); } } void Divide(int x,const int ff,const int num,int nowdep) { int root=x; if(num!=1) find_root(x,ff,num,nowdep-1,root); x=root; dep[x]=nowdep; fa[x]=ff; upd(x,ff,root); node t1=heap[x].top(); heap2[ff].push(node(t1.x,x,0)); heap2[x].push(node(0,x,0)); for(int k=fir[x];k;k=a[k].nex) { const int y=a[k].y; if(!dep[y]&&y!=ff) { int ny=siz[x]>siz[y]?siz[y]:num-siz[x]; dis[y][nowdep]=1; Divide(y,x,ny,nowdep+1); } } if(num==1) return; t1=heap2[x].top(); heap2[x].pop(); node t2=heap2[x].top(); Ans.push(node(t1.x+t2.x,x,0)); ans[x]=t1.x+t2.x; heap2[x].push(t1); return; } node get_top1(const int x) { node tmp; bool flag=false; while(!heap[x].empty()) { tmp=heap[x].top(); if(!light[tmp.i]) { flag=true; break; } heap[x].pop(); } if(!flag) tmp.i=-1; return tmp; } node get_top2(const int x) { node tmp,t1; bool flag=false; while(!heap2[x].empty()) { tmp=heap2[x].top(); heap2[x].pop(); if(tmp.ti!=th2[tmp.i]) continue; flag=true; break; } if(!flag) tmp.i=-1; return tmp; } void On(const int x) ///// { light[x]=true; countl--; th2[x]++; node t1,t2; t1=get_top1(x); if(t1.i!=-1&&fa[x]) heap2[fa[x]].push(node(t1.x,x,th2[x])); for(int i=fa[x];i;i=fa[i]) { th2[i]++; if(!light[i]) heap2[i].push(node(0,i,th2[i])); t1=get_top2(i); t2=get_top2(i); if(t1.i!=-1) heap2[i].push(t1); if(t2.i!=-1) heap2[i].push(t2); if(t2.i==-1) ans[i]=0; else if(t1.x+t2.x!=ans[i]) ans[i]=t1.x+t2.x,Ans.push(node(ans[i],i,0)); t1=get_top1(i); if(t1.i!=-1&&fa[i]) heap2[fa[i]].push(node(t1.x,i,th2[i])); } } void Off(const int x) ///// { light[x]=false; countl++; th2[x]++; node t1,t2; heap[x].push(node(dis[x][dep[x]-1],x,0)); heap2[x].push(node(0,x,th2[x])); t1=get_top2(x),t2=get_top2(x); if(t1.i!=-1) heap2[x].push(t1); if(t2.i!=-1) heap2[x].push(t2); if(t2.i!=-1&&t1.x+t2.x!=ans[x]) ans[x]=t1.x+t2.x,Ans.push(node(t1.x+t2.x,x,0)); for(int la=x,i=fa[x];i;la=i,i=fa[i]) { th2[i]++; if(!light[i]) heap2[i].push(node(0,i,th2[i])); t1=get_top1(la); heap2[i].push(node(t1.x,la,th2[la])); // t1=get_top2(i),t2=get_top2(i); if(t1.i!=-1) heap2[i].push(t1); if(t2.i!=-1) heap2[i].push(t2); if(t2.i!=-1&&t1.x+t2.x!=ans[i]) ans[i]=t1.x+t2.x,Ans.push(node(t1.x+t2.x,i,0)); heap[i].push(node(dis[x][dep[i]-1],x,0)); } } int main() { //light false read(n); countl=n; for(int i=1;i<n;i++) { int x,y; read(x); read(y); ins(x,y); ins(y,x); } Divide(1,0,n,1); char str[10]; read(m); for(int i=1;i<=m;i++) { scanf("%s",str); if(str[0]=='C') { int x; read(x); if(light[x]) Off(x); else On(x); } else { if(!countl) { printf("-1\n");continue; } if(countl==1) { printf("0\n");continue; } //// while(1) { node tmp=Ans.top(); if(ans[tmp.i]!=tmp.x) Ans.pop(); else { printf("%d\n",tmp.x); break; } } } } return 0; }
相关文章推荐
- 【BZOJ1095】【ZJOI2007】Hide 捉迷藏
- bzoj1095 [ZJOI2007]Hide 捉迷藏(括号序列+线段树/动态点分治+堆)
- 【BZOJ】1095: [ZJOI2007]Hide 捉迷藏 括号序列+线段树
- [动态点分治] BZOJ1095: [ZJOI2007]Hide 捉迷藏
- 【BZOJ 1095】 [ZJOI2007]Hide 捉迷藏 括号序列
- BZOJ 1095 [ZJOI2007]Hide 捉迷藏
- BZOJ1095: [ZJOI2007]Hide 捉迷藏
- [bzoj1095] [ZJOI2007]Hide 捉迷藏
- bzoj1095 [ZJOI2007]Hide 捉迷藏(动态点分治|括号序列)
- bzoj 1095 [ZJOI2007]Hide 捉迷藏(括号序列+线段树)
- bzoj1095 [ZJOI2007]Hide 捉迷藏
- bzoj1095 [ZJOI2007]Hide 捉迷藏(动态点分治+堆)
- 【BZOJ 1095】 [ZJOI2007]Hide 捉迷藏
- BZOJ 1095: [ZJOI2007]Hide 捉迷藏
- 【BZOJ1095】[ZJOI2007]Hide 捉迷藏【动态树分治】
- bzoj1095: [ZJOI2007]Hide 捉迷藏 动态点分治学习
- [BZOJ 1095] [ZJOI 2007]Hide 捉迷藏
- bzoj1095[ZJOI2007]Hide 捉迷藏
- bzoj 1095: [ZJOI2007]Hide 捉迷藏 动态树分治+堆
- BZOJ 1095 [ZJOI2007]Hide 捉迷藏