题目:
我是超链接
题解:
dfs序的in和out可以完美的把子树囊括在内,所以在维护的线段树上也是一段连续的区间,可以整体操作
首先关于安装问题,可以用状态0/1来表示
对于根到结点X的查询,非常容易
好了出于对树链剖分更深层次的理解,写一遍数组的意义:
in编号为i的点在线段树数组中的编号,sum编号为i的点在线段树中的存在的孩子个数【in是连接现实和虚拟的门。
添加软件包的时候,由于不是x的子树全部都要添加,必须呈链状修改
但删除就简单多了,呈团状子树全都没啦
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 100000
#define MIN -19e+7
using namespace std;
int size[N*4],ww[N*4],son[N*4],fa[N*4],deep[N*2+5],delta[N*4+5];
int top[N*4],in[N*4],out[N*4],totw=0;
int sum[N*4],maxn[N*4],minn[N*4];
int next[N*2+5],point[N*2+5],v[N*2+5],tot=0,cnt=0,n;
void addline(int x,int y)
{
++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y;
++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void updata(int now){sum[now]=sum[now<<1]+sum[now<<1|1];}
void dfs_1(int now,int dep,int faa)
{
deep[now]=dep;
fa[now]=faa;
size[now]=1;
int maxx=MIN;
for (int i=point[now];i;i=next[i])
if (v[i]!=faa)
{
dfs_1(v[i],dep+1,now);
size[now]+=size[v[i]];
if (size[v[i]]>maxx)
{
maxx=size[v[i]];
son[now]=v[i];
}
}
}
void dfs_2(int now,int faa)
{
if (son[faa]!=now) top[now]=now;
else top[now]=top[faa];
in[now]=++cnt;
if (son[now])
{
dfs_2(son[now],now);
for (int i=point[now];i;i=next[i])
if (v[i]!=son[now] && v[i]!=faa)
dfs_2(v[i],now);
}
out[now]=cnt;
}
void pushdown(int now,int l,int r,int mid)
{
if (delta[now]>=0)
{
delta[now<<1]=delta[now];
delta[now<<1|1]=delta[now];
sum[now<<1]=delta[now]*(mid-l+1);
sum[now<<1|1]=delta[now]*(r-mid);
delta[now]=-1;
}
}
int qurry(int now,int l,int r,int lrange,int rrange)
{
if (lrange<=l && rrange>=r) return sum[now];
int mid=(l+r)>>1,ans=0;
pushdown(now,l,r,mid);
if (mid>=lrange) ans+=qurry(now<<1,l,mid,lrange,rrange);
if (mid<rrange) ans+=qurry(now<<1|1,mid+1,r,lrange,rrange);
return ans;
}
void change(int now,int l,int r,int lrange,int rrange,int v)
{
if (l>=lrange && rrange>=r)
{
delta[now]=v;
sum[now]=v*(r-l+1);
return;
}
int mid=(l+r)>>1;
pushdown(now,l,r,mid);
if (mid>=lrange)change(now<<1,l,mid,lrange,rrange,v);
if (mid<rrange) change(now<<1|1,mid+1,r,lrange,rrange,v);
updata(now);
}
int work(int u,int v,int id)
{
int f1=top[u],f2=top[v],summ=0;
while (f1!=f2)
{
if (deep[f1]<deep[f2])
{
swap(f1,f2); swap(u,v);
}
if (id==1) summ+=qurry(1,1,n,in[f1],in[u]);
else change(1,1,n,in[f1],in[u],1);
u=fa[f1];
f1=top[u];
}
if (in[u]<in[v]) swap(u,v);
if (id==1) summ+=qurry(1,1,n,in[v],in[u]);
else change(1,1,n,in[v],in[u],1);
return summ;
}
int main()
{
int i,x,q;
scanf("%d",&n);
for (i=1;i<=n-1;i++)
{
scanf("%d",&x);
addline(i+1,x+1);
}
dfs_1(1,1,0);
dfs_2(1,0);
memset(delta,128,sizeof(delta));
scanf("%d",&q);
for (i=1;i<=q;i++)
{
char st[20];int ans=0;
scanf("%s%d",st,&x);
x++;
if (st[0]=='i')
{
ans=work(1,x,1);
printf("%d\n",deep[x]-ans);
ans=work(1,x,2);
}
else
{
ans=qurry(1,1,n,in[x],out[x]);
printf("%d\n",ans);
change(1,1,n,in[x],out[x],0);
}
}
}