#P8361. [ioi2018国家队集训]树

    ID: 8448 传统题 3000ms 512MiB 尝试: 24 已通过: 1 难度: 10 上传者: 标签>CF2900动态规划树状数组数据结构图论分块

[ioi2018国家队集训]树

树(tree)

题目描述

给定一棵有根树,共有 NN 个节点,节点编号为 0,1,,N10,1,\ldots,N-1,根节点为 00

对于每个 i=0,1,,N2i=0,1,\ldots,N-2,节点 i+1i+1 的父亲为 F[i]F[i]。保证:

0F[i]i0\le F[i]\le i

因此,每个节点的父亲编号都小于它本身的编号。

每个节点 uu 有一个点权 A[u]A[u],满足:

1A[u]L1\le A[u]\le L

定义一条长度为 LL 的节点序列 B[1],B[2],,B[L]B[1],B[2],\ldots,B[L] 是一条合法序列,当且仅当同时满足:

  1. 对于所有 i=1,2,,Li=1,2,\ldots,L,有:

    A[B[i]]=iA[B[i]]=i
  2. 对于所有 i=2,3,,Li=2,3,\ldots,L,节点 B[i]B[i] 是节点 B[i1]B[i-1] 的祖先。

也就是说,序列中点权依次为 1,2,,L1,2,\ldots,L,并且后一个节点必须是前一个节点的祖先。

现在会进行 QQ 次修改。第 ii 次修改,其中 0i<Q0\le i<Q,会把节点:

imodNi\bmod N

的点权修改为 P[i]P[i]

ansians_i 表示第 ii 次修改完成后,当前树上合法序列的数量。

你不需要输出每一次的 ansians_i,只需要计算:

$$O=\sum_{i=0}^{Q-1}(i+1)\times ans_i \pmod {10^9+7}$$

你的任务是实现指定函数,返回 OO


提交方式

本题为提交函数题。

你需要提交一个源文件,实现如下函数:

int calc(int N, int L, int Q,
         std::vector<int> F,
         std::vector<int> A,
         std::vector<int> P);

评测程序会负责读入数据并调用你的 calc 函数。

你提交的代码中:

  • 不应包含 main 函数;
  • 不需要自行读入;
  • 不需要自行输出;
  • 只需要返回答案 OO

参数说明

  • N:树的节点数。
  • L:合法序列的长度,也是点权的取值范围。
  • Q:修改次数。
  • F:长度为 N1N-1 的数组,其中 F[i] 表示节点 i+1i+1 的父亲。
  • A:长度为 NN 的数组,其中 A[i] 表示节点 ii 的初始点权。
  • P:长度为 QQ 的数组,其中 P[i] 表示第 ii 次修改后的新点权。
  • 函数需要返回整数 OO

样例

调用:

calc(6, 2, 6,
     {0, 1, 0, 3, 0},
     {1, 2, 1, 2, 1, 2},
     {2, 1, 2, 1, 2, 1});

在这个样例中:

ans = [0, 0, 1, 1, 2, 2]

因此:

$$O=1\times 0+2\times 0+3\times 1+4\times 1+5\times 2+6\times 2=29$$

所以函数应返回:

29

数据范围与限制

对于所有测试数据,满足:

  • 1N1061\le N\le 10^6
  • 1LN1\le L\le N
  • 1Q2×1061\le Q\le 2\times 10^6
  • 0F[i]i0\le F[i]\le i
  • 1A[i]L1\le A[i]\le L
  • 1P[i]L1\le P[i]\le L

子任务

  1. 1010 分:N200N\le 200L30L\le 30Q400Q\le 400
  2. 2020 分:N5000N\le 5000L300L\le 300Q5000Q\le 5000
  3. 2020 分:对于所有 ii,均有 F[i]=iF[i]=i
  4. 3030 分:N105N\le 10^5Q2×105Q\le 2\times 10^5
  5. 2020 分:无特殊限制。

样例评测程序说明

样例评测程序会按照如下格式读入数据:

N L Q
F[0] F[1] ... F[N-2]
A[0] A[1] ... A[N-1]
P[0] P[1] ... P[Q-1]

然后调用:

calc(N, L, Q, F, A, P)

并输出该函数的返回值。

输出格式为:

O