题解 P2056 【[ZJOI2007]捉迷藏 】
Great_Influence · · 题解
讲一下简单线段树做法。
首先,有一个结论:
现有集合
那么,根据这个结论,我们考虑利用线段树来维护区间直径。合并区间时直接暴力合并计算即可。
关于计算直径,需要知道两个点之间的
代码:
#include<bits/stdc++.h>
#define Rep(i,a,b) for(register int i=(a),i##end=(b);i<=i##end;++i)
#define Repe(i,a,b) for(register int i=(a),i##end=(b);i>=i##end;--i)
#define For(i,a,b) for(i=(a),i<=(b);++i)
#define Forward(i,a,b) for(i=(a),i>=(b);--i)
#define Chkmax(a,b) a=a>b?a:b
typedef unsigned int uint32;
inline uint32 getwd(void)
{
static const uint32 BUFSIZE = 1048576;
static char buf[BUFSIZE];
static char *bufnow = buf;
static char *bufmax = buf;
if (bufnow == bufmax) {
bufmax = buf + fread(buf, 1, BUFSIZE, stdin);
bufnow = buf;
}
return *bufnow++;
}
inline void read(uint32 &x){
static char k;k=getwd();x=0;
while(!isdigit(k)&&k^'-')k=getwd();
while(isdigit(k)){x=x*10+(k^48);k=getwd();}
}
inline void getopt(char &opt){for(opt=getwd();!isupper(opt);opt=getwd());}
inline void write(uint32 x)
{
static uint32 sta[35],tp;
if(!x){putchar(48),putchar('\n');return;}
for(tp=0;x;x/=10)sta[++tp]=x%10;
for(;tp;putchar(sta[tp--]^48));
putchar('\n');
}
using namespace std;
void file()
{
#ifndef ONLINE_JUDGE
freopen("practice.in","r",stdin);
freopen("practice.out","w",stdout);
#endif
}
const uint32 MAXN=5e5+7;
static uint32 n,e,head[MAXN],m;
static struct edge
{
uint32 v,nxt;
}p[MAXN<<1];
inline void add(uint32 u,uint32 v){p[++e]=(edge){v,head[u]};head[u]=e;}
static uint32 st[MAXN],dfn[MAXN],las[MAXN],fa[20][MAXN],dep[MAXN],re[MAXN];
void dfs(uint32 u,uint32 fr)
{
re[dfn[u]=++e]=u;fa[0][u]=fr;dep[u]=dep[fr]+1;
for(register uint32 v=head[u];v;v=p[v].nxt)if(p[v].v^fr)dfs(p[v].v,u);
las[u]=e;
}
static uint32 Log[MAXN];
inline void init()
{
read(n);
static uint32 u,v;
Rep(i,1,n-1)read(u),read(v),add(u,v),add(v,u);e=0;
dfs(1,0);
Rep(i,2,n)Log[i]=Log[i>>1]+1;
Rep(j,1,Log[n])Rep(i,1,n)fa[j][i]=fa[j-1][fa[j-1][i]];
}
inline uint32 dist(uint32 u,uint32 v)
{
u=re[u];v=re[v];
static uint32 dps;dps=dep[u]+dep[v];
if(dep[u]<dep[v])swap(u,v);
for(;dep[u]-dep[v];u=fa[Log[dep[u]-dep[v]]][u]);
if(u==v)return dps-2*dep[u];
Repe(i,Log[dep[u]],0)if(fa[i][u]^fa[i][v])u=fa[i][u],v=fa[i][v];
return dps-2*dep[u]+2;
}
namespace Segment_Tree
{
static uint32 poi[MAXN<<2][3],dst[MAXN<<2];
inline void pushup(uint32 h)
{
static uint32 dis;
dst[h]=-1;poi[h][0]=poi[h][1]=poi[h][2]=0;
if(dst[h<<1]==-1)
{
dst[h]=dst[h<<1|1],poi[h][0]=poi[h<<1|1][0];
poi[h][1]=poi[h<<1|1][1],poi[h][2]=poi[h<<1|1][2];
}
else if(dst[h<<1|1]==-1)
{
dst[h]=dst[h<<1],poi[h][0]=poi[h<<1][0];
poi[h][1]=poi[h<<1][1],poi[h][2]=poi[h<<1][2];
}
else
{
if(dst[h<<1]<dst[h<<1|1])
{
dst[h]=dst[h<<1|1],poi[h][0]=poi[h<<1|1][0];
poi[h][1]=poi[h<<1|1][1],poi[h][2]=poi[h<<1|1][2];
}
else
{
dst[h]=dst[h<<1],poi[h][0]=poi[h<<1][0];
poi[h][1]=poi[h<<1][1],poi[h][2]=poi[h<<1][2];
}
Rep(i,1,poi[h<<1][0])Rep(j,1,poi[h<<1|1][0])
if((dis=dist(poi[h<<1][i],poi[h<<1|1][j]))>dst[h])
dst[h]=dis,poi[h][1]=poi[h<<1][i],poi[h][2]=poi[h<<1|1][j];
poi[h][0]=2;
}
}
void make_tree(uint32 h,uint32 l,uint32 r)
{
if(l==r)
{
st[l]=1;poi[h][0]=1;poi[h][1]=l;
return;
}
uint32 mid=(l+r)>>1;
make_tree(h<<1,l,mid);make_tree(h<<1|1,mid+1,r);
pushup(h);
}
void modify(uint32 h,uint32 l,uint32 r,uint32 x)
{
if(l==r)
{
if(st[l])st[l]=poi[h][0]=poi[h][1]=0,dst[h]=-1;
else st[l]=poi[h][0]=1,poi[h][1]=l,dst[h]=0;
return;
}
static uint32 mid;mid=(l+r)>>1;
x<=mid?modify(h<<1,l,mid,x):modify(h<<1|1,mid+1,r,x);
pushup(h);
}
static uint32 dsts,pi[3];
inline void Combine(uint32 h)
{
static uint32 u,v,dis;
if(!poi[h][0])return;
if(!pi[0])pi[0]=poi[h][0],pi[1]=poi[h][1],pi[2]=poi[h][2],dsts=dst[h];
else
{
if(dst[h]>dsts)dsts=dst[h],u=poi[h][1],v=poi[h][2];
else u=pi[1],v=pi[2];
Rep(i,1,pi[0])Rep(j,1,poi[h][0])
if((dis=dist(pi[i],poi[h][j]))>dsts)
dsts=dis,u=pi[i],v=poi[h][j];
pi[0]=2;pi[1]=u;pi[2]=v;
}
}
void query(uint32 h,uint32 l,uint32 r,uint32 x,uint32 y)
{
if(l>=x&&r<=y)
{
Combine(h);
return;
}
uint32 mid=(l+r)>>1;
if(x<=mid)query(h<<1,l,mid,x,y);
if(y>mid)query(h<<1|1,mid+1,r,x,y);
}
}
using namespace Segment_Tree;
inline void solve()
{
read(m);
static char x;
static uint32 rt;
make_tree(1,1,n);
Rep(i,1,m)
{
getopt(x);read(rt);
if(x=='C')modify(1,1,n,dfn[rt]);
else
{
pi[0]=pi[1]=pi[2]=0;dsts=-1;
query(1,1,n,dfn[rt],las[rt]);
~dsts?write(dsts):(void)puts("-1");
}
}
cerr<<1.0*clock()/CLOCKS_PER_SEC<<endl;
}
int main()
{
file();
init();
solve();
return 0;
}