题目大意:给出一个n个点的有根树,和m次操作;
初始时树上所有结点权值均为0;
1.将根到x结点的所有结点权值置为1,并输出这次修改了多少个元素;
2.将x结点的子树中所有结点权值置为0,并输出这次修改了多少个元素
题解:剖剖剖
我的收获:注意编号从0/1开始
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int M=100005;
int q,n,t,tim,head[M];
int dfn[M],end[M];
struct edge{int to,nex;}e[M<<1];
void add(int u,int v){e[t].to=v,e[t].nex=head[u],head[u]=t++;}
namespace stree{
#define ls x<<1
#define rs x<<1|1
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
#define root 1,n,1
int sum[M<<2],cov[M<<2];
inline void pushup(int x){sum[x]=sum[ls]+sum[rs];}
inline void pushdown(int x,int m){
if(cov[x]==-1||m==1) return ;
cov[ls]=cov[rs]=cov[x];
sum[ls]=cov[x]*(m-(m>>1));
sum[rs]=cov[x]*(m>>1);
cov[x]=-1;
}
void build(int l,int r,int x)
{
cov[x]=-1;
if(l==r) return ;
int m=(l+r)>>1;
build(lson),build(rson);
}
void update(int L,int R,int k,int l,int r,int x)
{
if(L<=l&&r<=R){cov[x]=k,sum[x]=(r-l+1)*k;return ;}
pushdown(x,r-l+1);
int m=(l+r)>>1;
if(L<=m) update(L,R,k,lson);
if(R>m) update(L,R,k,rson);
pushup(x);
}
int query(int L,int R,int l,int r,int x)
{
if(L<=l&&r<=R) return sum[x];
pushdown(x,r-l+1);
int m=(l+r)>>1,ret=0;
if(L<=m) ret+=query(L,R,lson);
if(R>m) ret+=query(L,R,rson);
return ret;
}
}
namespace hld{
int sz[M],fa[M],dep[M],son[M],top[M];
void predfs(int x)
{
sz[x]=1;
for(int i=head[x];i!=-1;i=e[i].nex){
int v=e[i].to;
if(v==fa[x]) continue;
fa[v]=x,dep[v]=dep[x]+1;
predfs(v);sz[x]+=sz[v];
if(sz[v]>sz[son[x]]) son[x]=v;
}
}
void dfs(int x,int tp)
{
dfn[x]=++tim;top[x]=tp;
if(son[x]) dfs(son[x],tp);
for(int i=head[x];i!=-1;i=e[i].nex){
int v=e[i].to;
if(v!=fa[x]&&v!=son[x]) dfs(v,v);
}
end[x]=tim;
}
int ask(int x,int y)
{
int f1=top[x],f2=top[y],sum=0,num=dep[y]-dep[x]+1;//!!!
while(f1!=f2){
if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
sum+=stree::query(dfn[f1],dfn[x],root);
stree::update(dfn[f1],dfn[x],1,root);
x=fa[f1],f1=top[x];
}
if(dep[x]>dep[y]) swap(x,y);
sum+=stree::query(dfn[x],dfn[y],root);
stree::update(dfn[x],dfn[y],1,root);
return num-sum;
}
}
void work()
{
char opt[11];int x;
while(q--){
scanf("%s%d",opt,&x);x++;
if(opt[0]=='i') printf("%d\n",hld::ask(1,x));
if(opt[0]=='u') printf("%d\n",stree::query(dfn[x],end[x],root)),stree::update(dfn[x],end[x],0,root);
}
}
void init()
{
cin>>n;memset(head,-1,sizeof(head));
for(int i=2,x;i<=n;i++) scanf("%d",&x),x++,add(x,i),add(i,x);
cin>>q;
hld::predfs(1);hld::dfs(1,1);
stree::build(root);
}
int main()
{
init();
work();
return 0;
}