您的位置:首页 > 其它

BZOJ1095: [ZJOI2007]Hide 捉迷藏

2017-03-30 09:22 381 查看
所以为什么这道是动态点分治的模板题….细节好爆炸

动态点分治按每次分治的重心建树,然后在分治的过程中处理出每个点在原树中到它新树中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;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: