Luogu2056 [ZJOI2007]捉迷藏
Luogu2056 [ZJOI2007]捉迷藏
这道题是最远点对问题,考虑如何用点分治维护最远点对。
那么对于每一个点,我们只需要找到最长链和次长链(如果有的话),由于需要动态维护点分树,我们需要数据结构,可删除堆可以胜任这一任务(以下提到的堆均为可删除堆,关于可删除堆的操作细节,这里就不谈了,现在我才知道自己写的可删除堆是如此逊,不会用两个堆写到爆炸)。
但是不能忘记,如果我们要计算一个节点\(u\)控制的连通块\(T_u\)答案,在这两条链是不能同时存在于\(u\)的同一颗子树内的。
那么对于每一棵子树\(v\)维护一个堆\(H_{u,v}\),再用每一棵子树的堆顶元素丢进一个堆\(R_{u}\)里,那么\(R_{u}\)的前两大元素即为连通块\(T_u\)内的最长链。
由于我们需要求全局答案,因此我们还需要维护一个堆\(ans\),容纳所有\(R_x\)的堆顶元素最大值。
于是变成了堆套堆套堆,十分奇怪。
然后我们考虑修改,从询问节点\(x\)开始往上跳到点分树根,由于我们维护的是堆套堆套堆,所以我们每次修改都需要修改\(3\)个堆,先修改底层的\(H\),再修改\(R\),最后修改\(ans\)。
然后,就被卡常了。。。
关于卡常的坎坷,这里不再叙述(常数大怪谁呢,口胡可删除堆怪谁呢)。
注:以下代码中没有把\(dis_{u,u}=0\)丢进\(R_u\)中,因此如果\(R_u\)中只有一条链,那么需要特判\(u\)是否被点亮,如果没被点亮,这条链答案是需要统计进去的,否则不能统计(只有一个端点)。
\(Code:\)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<tr1/unordered_map>
#define N 100005
#define INF 1000000007
#define rint register int
#define il inline
#define pr pair<int,int>
#define mp make_pair
#define IT vector<int> :: iterator
using namespace std;
using namespace std :: tr1;
int n,m,x,y,o;
int tot,fr[N],nxt[N << 1],d[N << 1];
int lsz,rtsz,rt,ct,f[N],sz[N];
int crt,trt,krt,light;
char opt;
bool vis[N],op[N];
int tr[N];
int tc,bg[N],lg2[N << 1],dep[N],dfn[N << 1],st[N << 1][20];
char buf[1 << 23],*p1=buf,*p2=buf,obuf[1 << 23],*O=obuf;
#define getchar() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1 << 21,stdin),p1==p2)?EOF:*p1++)
unordered_map<int,int>r[N];
unordered_map<int,int>g[N << 1];
struct Heap
{
vector<int>a;
vector<int>c;
int cnt,id;
il pr top()
{
return mp(a[1],c[1]);
}
il bool empty()
{
return cnt==0;
}
il int size()
{
return cnt;
}
il void push(int x,int z)
{
++cnt;
a.push_back(x);
c.push_back(z);
g[id][z]=cnt;
int t=cnt;
while (t>1 && a[t]>a[t >> 1])
{
swap(g[id][c[t]],g[id][c[t >> 1]]);
swap(a[t],a[t >> 1]);
swap(c[t],c[t >> 1]);
t >>=1;
}
}
il void pop()
{
swap(g[id][c[cnt]],g[id][c[1]]);
swap(a[cnt],a[1]);
swap(c[cnt],c[1]);
g[id][c[cnt]]=0;
a.erase(a.end()-1);
c.erase(c.end()-1);
cnt--;
int t=1;
while ((t << 1)<=cnt && a[t]<a[t << 1] || (t << 1 | 1)<=cnt && a[t]<a[t << 1 | 1])
if ((t << 1 | 1)>cnt || a[t << 1]>a[t << 1 | 1])
swap(g[id][c[t]],g[id][c[t << 1]]),swap(a[t],a[t << 1]),swap(c[t],c[t << 1]),t <<=1; else
swap(g[id][c[t]],g[id][c[t << 1 | 1]]),swap(a[t],a[t << 1 | 1]),swap(c[t],c[t << 1 | 1]),t=t << 1 | 1;
}
il void pop_point(int z)
{
int wz=g[id][z];
if (!wz)
return;
swap(g[id][c[cnt]],g[id][c[wz]]);
swap(a[cnt],a[wz]);
swap(c[cnt],c[wz]);
g[id][c[cnt]]=0;
a.erase(a.end()-1);
c.erase(c.end()-1);
cnt--;
int t=wz;
while (t>1 && a[t]>a[t >> 1])
{
swap(g[id][c[t]],g[id][c[t >> 1]]);
swap(a[t],a[t >> 1]);
swap(c[t],c[t >> 1]);
t >>=1;
}
while ((t << 1)<=cnt && a[t]<a[t << 1] || (t << 1 | 1)<=cnt && a[t]<a[t << 1 | 1])
if ((t << 1 | 1)>cnt || a[t << 1]>a[t << 1 | 1])
swap(g[id][c[t]],g[id][c[t << 1]]),swap(a[t],a[t << 1]),swap(c[t],c[t << 1]),t <<=1; else
swap(g[id][c[t]],g[id][c[t << 1 | 1]]),swap(a[t],a[t << 1 | 1]),swap(c[t],c[t << 1 | 1]),t=t << 1 | 1;
}
void update_point(int x,int z)
{
int wz=g[id][z];
if (!wz)
{
push(x,z);
return;
}
a[wz]=x;
int t=wz;
while (t>1 && a[t]>a[t >> 1])
{
swap(g[id][c[t]],g[id][c[t >> 1]]);
swap(a[t],a[t >> 1]);
swap(c[t],c[t >> 1]);
t >>=1;
}
while ((t << 1)<=cnt && a[t]<a[t << 1] || (t << 1 | 1)<=cnt && a[t]<a[t << 1 | 1])
if ((t << 1 | 1)>cnt || a[t << 1]>a[t << 1 | 1])
swap(g[id][c[t]],g[id][c[t << 1]]),swap(a[t],a[t << 1]),swap(c[t],c[t << 1]),t <<=1; else
swap(g[id][c[t]],g[id][c[t << 1 | 1]]),swap(a[t],a[t << 1 | 1]),swap(c[t],c[t << 1 | 1]),t=t << 1 | 1;
}
}e[N << 1];
il int cmx(int x,int y)
{
return (x>y)?x:y;
}
il void ins(int x,int y)
{
r[x][y]=++ct;
e[ct].id=ct;
e[ct].cnt=0;
e[ct].a.push_back(0);
e[ct].c.push_back(0);
}
il void ins(int x)
{
tr[x]=++ct;
e[ct].id=ct;
e[ct].cnt=0;
e[ct].a.push_back(0);
e[ct].c.push_back(0);
}
il int ans(int x,int tx)
{
if (!x)
return (!light)?(-1):((light^1)?e[x].top().first:0);
if (e[x].empty())
return 0;
return (e[x].size()==1)?(op[tx]?0:e[x].a[1]):((e[x].size()==2)?e[x].a[1]+e[x].a[2]:e[x].a[1]+cmx(e[x].a[2],e[x].a[3]));
}
il int read()
{
int s=0;
char c=getchar();
while (c<'0' || c>'9')
c=getchar();
while ('0'<=c && c<='9')
s=(s << 1)+(s << 3)+(c^48),c=getchar();
return s;
}
il void write(int x)
{
if (x<0)
*O++='-',write(-x); else
{
if (x>9)
write(x/10);
*O++=x%10+'0';
}
}
il void add(int x,int y)
{
tot++;
d[tot]=y;
nxt[tot]=fr[x];
fr[x]=tot;
}
il void dfs(int u,int F)
{
dfn[++tc]=u;
bg[u]=tc;
for (rint i=fr[u];i;i=nxt[i])
{
int v=d[i];
if (v==F)
continue;
dep[v]=dep[u]+1;
dfs(v,u);
dfn[++tc]=u;
}
}
il int lca(int x,int y)
{
x=bg[x],y=bg[y];
if (x>y)
swap(x,y);
int k=lg2[y-x+1];
return (dep[st[x][k]]<dep[st[y-(1 << k)+1][k]])?st[x][k]:st[y-(1 << k)+1][k];
}
il int ds(int x,int y)
{
return dep[x]+dep[y]-(dep[lca(x,y)] << 1);
}
il void findrt(int u,int F,int rn)
{
int mx=-1;
sz[u]=1;
for (rint i=fr[u];i;i=nxt[i])
{
int v=d[i];
if (v==F || vis[v])
continue;
findrt(v,u,rn);
sz[u]+=sz[v];
if (sz[v]>mx)
mx=sz[v];
}
mx=cmx(mx,rn-sz[u]);
if (mx<rtsz)
rtsz=mx,rt=u;
}
il void getrt(int u,int rn)
{
rtsz=INF;
findrt(u,0,rn);
}
il void update_dis(int u,int F)
{
e[crt].push(ds(trt,u),u);
for (rint i=fr[u];i;i=nxt[i])
{
int v=d[i];
if (v==F || vis[v])
continue;
update_dis(v,u);
}
}
il void solve(int u)
{
int tsz=lsz;
vis[u]=true;
if (tsz==1)
return;
ins(u);
for (rint i=fr[u];i;i=nxt[i])
{
int v=d[i];
if (vis[v])
continue;
lsz=(sz[v]<sz[u])?sz[v]:tsz-sz[u];
getrt(v,lsz);
f[rt]=u;
ins(u,rt);
trt=u,krt=rt,crt=ct;
update_dis(v,u);
e[tr[u]].push(e[ct].top().first,rt);
solve(rt);
}
e[0].push(ans(tr[u],u),u);
}
il void insr(int x,int t,int y)
{
o=r[x][t];
e[o].push(ds(x,y),y);
e[tr[x]].update_point(e[o].top().first,t);
e[0].update_point(ans(tr[x],x),x);
}
il void del(int x,int t,int y)
{
o=r[x][t];
e[o].pop_point(y);
if (e[o].empty())
e[tr[x]].pop_point(t); else
e[tr[x]].update_point(e[o].top().first,t);
if (e[tr[x]].empty())
e[0].pop_point(x); else
e[0].update_point(ans(tr[x],x),x);
}
il void update(int x,int opt)
{
int u=x;
while (f[u])
{
if (!opt)
insr(f[u],u,x); else
del(f[u],u,x);
u=f[u];
}
}
int main()
{
n=read();
for (rint i=1;i<n;++i)
{
x=read(),y=read();
add(x,y),add(y,x);
}
dep[1]=1;
dfs(1,0);
lg2[0]=-1;
for (rint i=1;i<=tc;++i)
st[i][0]=dfn[i],lg2[i]=lg2[i >> 1]+1;
for (rint j=1;j<=lg2[tc];++j)
for (rint i=1;i<=tc-(1 << j)+1;++i)
st[i][j]=(dep[st[i][j-1]]<dep[st[i+(1 << (j-1))][j-1]])?st[i][j-1]:st[i+(1 << (j-1))][j-1];
ct=0;
e[ct].id=ct;
e[ct].cnt=0;
e[ct].a.push_back(0);
e[ct].c.push_back(0);
lsz=n;
getrt(1,lsz);
solve(rt);
light=n;
m=read();
for (rint i=1;i<=m;++i)
{
opt=getchar();
while (opt!='C' && opt!='G')
opt=getchar();
if (opt=='G')
write(ans(0,0)),*O++='\n'; else
{
x=read();
int tt=-1;
if (op[x])
light++,op[x]=false,tt=0; else
light--,op[x]=true,tt=1;
update(x,tt);
}
}
fwrite(obuf,O-obuf,1,stdout);
return 0;
}