给定一棵 N N N 个结点的树,定义一次操作如下:选择一个非根结点 x x x,其父亲为 y y y,则该操作将删除点 y y y,并且将 x x x 的父亲设置为 y y y 原本的父亲,并将原本 y y y 的其余儿子的父亲设置为 x x x。
现在结点 1 ⋯ N 1 \cdots N 1⋯N 将被依次染成黑色。假设结点 1 ⋯ K 1 \cdots K 1⋯K 被染为黑色,你需要对所有点求出 f i f_i fi,表示在经过任意多次操作后,从点 i i i 出发向上连续最多有几个黑点(点𝑖为白色时 f i f_i fi = 0)。记 s K s_K sK 为此时所有 f i f_i fi 的和,你需要求出 s 1 × s 2 × ⋯ × s N s_1 \times s_2 \times \cdots \times s_N s1×s2×⋯×sN,对 1 0 9 + 7 10^9 + 7 109+7 取模。
注意:对于每个 f i f_i fi 的计算是独立的。
第一行一个正整数 N N N。
接下来 N N N 行,每行一个数 f a [ i ] fa[i] fa[i], f a [ i ] = 0 fa[i] = 0 fa[i]=0 的点是根结点。
一个数表示答案。
样例输入 1
6
4
3
4
0
5
3
样例输出 1
13440
样例输入 2
12
7
8
2
3
6
2
2
0
5
3
4
1
样例输出 2
416049631
T T T | N ≤ N\leq N≤ | 特殊约定 |
---|---|---|
1 , 2 , 3 1,2,3 1,2,3 | 100 100 100 | |
4 , 5 , 6 4,5,6 4,5,6 | 800000 800000 800000 | 树是一条链 |
7 , 8 , 9 , 10 7,8,9,10 7,8,9,10 | 800000 800000 800000 |
我们发现答案即为每个祖先节点除了当前链的子树中是否有染色节点,是的话贡献为1的总和的点的总和。
修改只需要暴力跳父亲即可。用树状数组维护。
不难。。
#include<bits/stdc++.h>
#define N 800005
using namespace std;
const int mod=1e9+7;
int read(){
int op=1,sum=0;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') op=-1;ch=getchar();}
while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+ch-'0',ch=getchar();
return op*sum;
}
int dfs_num,dfn[N],sz[N],rot,fa[N];
vector<int> to[N];
void dfs(int x,int las){
sz[x]=1;
dfn[x]=++dfs_num;
for(int i=0;i<to[x].size();++i){
int y=to[x][i];
if(y==las)continue;
dfs(y,x);
sz[x]+=sz[y];
}
}
inline void add(int &x,int y){x=(x+y>=mod)?x+y-mod:x+y;}
struct BIT{
int t[N];
inline void init(){
memset(t,0,sizeof(t));
}
inline int lowbit(int x){return x&(-x);}
inline int get(int x){
int now=0;
for(;x;x-=lowbit(x))add(now,t[x]);
return now;
}
inline void ch(int x,int val){
for(;x<=dfs_num;x+=lowbit(x))add(t[x],val);
}
}T[2];
inline int ct(int x){
return T[1].get(dfn[x]+sz[x]-1)-T[1].get(dfn[x]-1);
}
int main(){
int n=read();
for(int i=1;i<=n;++i){
int x=read();fa[i]=x;
if(!x)rot=i;
else to[x].push_back(i),to[i].push_back(x);
}
dfs(rot,0);
int ans=0,sum=1;
T[0].init();T[1].init();
for(int i=1;i<=n;++i){
int x=i;
add(ans,T[0].get(dfn[i])+1);
while(x!=rot&&ct(x)==0){
if(fa[x]<=i)break;
int cs=ct(fa[x])-ct(x);
for(int j=0;j<to[fa[x]].size();++j){
int y=to[fa[x]][j];
if(y==fa[fa[x]]||y==x)continue;
if(ct(y)==cs){
T[0].ch(dfn[y],1);T[0].ch(dfn[y]+sz[y],-1);
add(ans,ct(y));
}
}
x=fa[x];
}
x=i;
for(int j=0;j<to[x].size();++j){
int y=to[x][j];
if(y==fa[i])continue;
if(ct(y)==ct(x)){
T[0].ch(dfn[y],1);T[0].ch(dfn[y]+sz[y],-1);
add(ans,ct(y));
}
}
T[1].ch(dfn[i],1);
sum=1ll*sum*ans%mod;
}
printf("%d\n",(sum+mod)%mod);
return 0;
}