【题解】ADAGRAFT - Ada and Graft [SP33331]

传送门:\(\text{Ada and Graft}\) \(\text{[SP33331]}\)

【题目描述】

给出一颗 \(n\) 个节点的树(根为 \(0\)),树的价值定义为每个节点的价值乘积。每个节点的值是其子树中不同颜色种类的数量。

给出每个节点上的颜色,求树价值。答案对 \(10^9+7\) 取模。

【输入】

第一行包含一个整数 \(n\)。

第二行包含 \(n-1\) 个整数 \(p_{i}\),分别表示节点 \(i\) 的父亲节点。

第三行包含 \(n\) 个整数 \(F_{i}\),表示节点 \(i\) 的颜色。

【输出】

输出一个整数表示答案模 \(10^9+7\) 的值。

【样例】

样例输入1:
5
0 0 1 1
1 1 1 2 2 样例输出1:
4 样例输入2:
4
0 1 2
6 7 2 3 样例输出2:
24 样例输入3
11
0 1 1 1 3 5 2 7 5 4
494052753 959648710 959648710 959648710 494052753 959648710 959648710 959648710 959648710 494052753 959648710 样例输出3
32

【数据范围】

\(100\%\) \(1 \leqslant N \leqslant 4*10^5,\) \(1 \leqslant F_{i} \leqslant 10^9,\) \(0 \leqslant p_{i} \leqslant i\)


【分析】

求以某个节点为根的子树信息,很明显的线段树合并。

考虑将所有点的权值离散化一下,对每个节点开一颗动态开点权值线段树,按照 \(dfs\) 的遍历顺序不断合并所有子节点,便可得到所有节点的价值,最后乘起来即可。

合并两个权值线段树时可以直接取 \(or\),向上传递信息直接 \(S[p]=S[pl]+S[pr]\)。

注意取模!!!

【Code】

#include<algorithm>
#include<cstdio>
#define LL long long
#define Re register int
using namespace std;
const int N=4e5+3,P=1e9+7;
int n,m,x,y,o,Ans=1,A[N],B[N],pt[N],ans[N],head[N];
struct QAQ{int to,next;}a[N<<1];
inline void add(Re x,Re y){a[++o].to=y,a[o].next=head[x],head[x]=o;}
inline void in(Re &x){
Re fu=0;x=0;char ch=getchar();
while(ch<'0'||ch>'9')fu|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=fu?-x:x;
}
struct Segment_Tree{
#define pl tr[p].lp
#define pr tr[p].rp
#define mid (L+R>>1)
int cnt;
struct QAQ{int S,lp,rp;}tr[N*38];//空间要开够
inline void pushup(Re p){tr[p].S=tr[pl].S+tr[pr].S;}
inline void change(Re &p,Re L,Re R,Re w){
if(!p)p=++cnt;
if(L==R){tr[p].S=1;return;}
if(w<=mid)change(pl,L,mid,w);
else change(pr,mid+1,R,w);
pushup(p);
}
inline int merge(Re p,Re q,Re L,Re R){
if(!p)return q;if(!q)return p;
if(L==R){tr[p].S|=tr[q].S;return p;}//合并信息
pl=merge(pl,tr[q].lp,L,mid);
pr=merge(pr,tr[q].rp,mid+1,R);
pushup(p);return p;
}
}T1;
inline void dfs(Re x,Re fa){
for(Re i=head[x],to;i;i=a[i].next)
if((to=a[i].to)!=fa)
dfs(to,x),pt[x]=T1.merge(pt[x],pt[to],1,m);
ans[x]=T1.tr[pt[x]].S;//直接获取整个大区间的答案
}
int main(){
// freopen("123.txt","r",stdin);
in(n);
for(Re i=2;i<=n;++i)in(x),add(++x,i),add(i,x);
for(Re i=1;i<=n;++i)in(A[i]),B[i]=A[i];
sort(B+1,B+n+1),m=unique(B+1,B+n+1)-B-1;
for(Re i=1;i<=n;++i)T1.change(pt[i],1,m,lower_bound(B+1,B+m+1,A[i])-B);//初始化建树
dfs(1,0);
for(Re i=1;i<=n;++i)Ans=(LL)Ans*ans[i]%P;
printf("%d\n",Ans);
}

【题解】ADAGRAFT - Ada and Graft [SP33331]的更多相关文章

  1. SPOJ:Ada and Graft (set合并&优化)

    As you might already know, Ada the Ladybug is a farmer. She grows a big fruit tree (with root in 0). ...

  2. SPOJ ADAFIELD Ada and Field(STL的使用:set,multiset,map的迭代器)题解

    题意:n*m的方格,“0 x”表示x轴在x位置切一刀,“0 y”表示y轴在y位置切一刀,每次操作后输出当前面积最大矩形. 思路:用set分别储存x轴y轴分割的点,用multiset(可重复)储存x轴y ...

  3. Ada and Coins

    Ada and Coins 题意:钱包里有n种钱,然后有m次询问,询问[l,r]区间内能被表示的个数有几个. 题解:这道题是群主推荐我写的,然后让我用bitset去写,他说 操作32个bitset需要 ...

  4. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  5. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  6. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  7. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  8. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  9. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

随机推荐

  1. PlayJava Day011

    今日所学: /* 2019.08.19开始学习,此为补档. */ Java异常处理 1.异常的概念:程序运行过程中发生的问题,从而引发了中断. 2.捕获和处理异常:Java中,用try ... cat ...

  2. C++ 成员对象和封闭类

    01 成员对象与封闭类 类里有其他对象则该对象叫成员对象:有成员对象的类叫 封闭类: class CTyre // 轮胎类 { public: // 有参数构造函数 // 初始化成员变量m_radiu ...

  3. NetCoreAPI添加Swagger

    public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; ...

  4. 并发修改异常ConcurrentModificationException

    1.简述:在使用 迭代器对象遍历集合时,使用集合对象修改集合中的元素导致出现异常 public static void main(String[] args) { List<Integer> ...

  5. 第十章 Centos7-系统进程管理

    第十章  Centos7-系统进程管理 本节所讲内容: 10.1  进程概述和ps查看进程工具 10.2  uptime查看系统负载-top动态管理进程 10.3  前后台进程切换- nice进程优先 ...

  6. 【转】gdb的调试与使用

    转载自:https://www.jianshu.com/p/7a06b0bda2d8 gdb的调试与使用 这篇应该是我见过的总结最详细的gdb调试指南了,这位博主是个很强的人,他的博客对萌新比较友好, ...

  7. Python3面向对象编程实例

    /*认真研究完这个实例,理解python面向对象编程的方法*/class Person: """人员信息""" # 姓名(共有属性) nam ...

  8. C语言中如何求最大公约数及如何求最小公倍数。

    最大公约数:                                                                                               ...

  9. 关于一个.2lf和.2f的战争!(貌似书上错了,静待打脸。)

    在山东理工oj上做题,谈到了输入数据... double i: scanf(“%lf”,&i): 谨记呀,lf时,可以输入任何类型的数据,而.2f,只能输入符合其规格的数据. 再谈输出,dou ...

  10. 事件代理/事件委托----点击li弹出对应的下标和内容

    <body> <ul> <li>这是第一行</li> <li>这是第二行</li> <li>这是第三行</li ...