CSP 2018年3月 第5题 二次求和

试题编号: 201803-5
试题名称: 二次求和
时间限制: 10.0s
内存限制: 512.0MB
问题描述:

问题描述

  给一棵 n 个节点的树,用 1 到 n 的整数表示。每个节点上有一个整数权值 ai。再给出两个整数 L,R。现在有 m 个操作,每个操作这样描述:
  给定树上两个节点 u,v 和一个整数 d,表示将树上 u 到 v 唯一的简单路径上每个点的权值 ai 都加上 d。之后求树上所有节点个数大于等于 L 小于等于 R 的简单路径的节点权值和之和。注意这里有两次求和:对于一条节点个数大于等于 L 小于等于 R 的简单路径,求出它所有节点的权值之和;然后对所有这样的路径,对它们的权值和再进行求和。因为答案很大,只用输出对Q=1,000,000,007 取余的结果即可。

输入格式

  从标准输入读入数据。
  包含多组数据。数据的第一行包含一个正整数 T,表示数据组数。保证 T=10。
  每组数据的第一行包含 4 个非负整数 n,m,L,R,分别表示节点个数、操作个数和询问相关的两个参数。保证 1≤L≤R≤n。
  第二行包含 n 个整数,表示 ai。保证 0≤ai<Q。
  第三行包含 n-1 个整数,描述树的形态,其中第 i 个数 fi 表示节点 i+1 与节点 fi 之间有一条边,保证 1≤fi≤i<n。能够证明,这样能够保证给出的是一棵树。
  接下来 m 行,每行包含三个整数 u,v,d,描述一个操作即将树上 u 到 v 唯一的简单路径上每个点的权值 ai 都加上 d,之后询问满足条件的两次求和的结果。保证 1≤u,v≤n,0≤d<Q。
  保证上述同一行所有的数之间,均用一个空格隔开。

输出格式

  输出到标准输出。
  输出 m 行每行一个整数,表示两次求和的结果对 Q=1000000007 求余的结果。
  子任务
  共有 10 个测试点,各测试点特点如下:
  测试点1:n=10,m=10。
  测试点2:n=50,m=50。
  测试点3:n=300,m=300。
  测试点4:n=2000,m=2000。
  测试点5:n=2000,m=100000。
  测试点6:n=100000,m=100000。保证 fi=i。
  测试点7:n=100000,m=100000。保证 fi=⌊(i+1)/2⌋,其中 ⌊⋅⌋ 表示向下取整,即给定的树是完全二叉树。
  测试点8:n=100000,m=100000。保证对于同一组数据,相同的 fi 至多出现 2 次,即给定的树是二叉树。
  测试点9:n=100000,m=100000。
  测试点10:n=100000,m=100000。
  上述约束对同一测试点中的每组数据都有效。

 

写题解前先吐槽。。。

这个题大概我高二的时候就已经见过比这个还要难的点分治了,然而大二才会,这么多年真是活到狗身上去了orz

ccf这个题库的栈空间真是小的一匹,估计是windows

这个题还卡常数,开了fread各种搞常数才卡时限9.25s过,去掉fread只有60分,不知道比赛评测是不是会快一点

当然我是O(nlog^2(n))的做法,套个树状数组,不知道有没有更优雅的做法不用卡常数

upd:手写queue之后跑了6.4s,但是不加fread还是只有60。

题意如上,考虑每个点权a(u)对答案的贡献,就是a(u)*经过u且长度在[L,R]之间的路径条数,路径条数记为path(u)

对于修改(u,v,d)来说,只需要考虑这个修改的贡献,也就是用d乘上u到v路径上所有点的path(i)的和

所以考虑预处理出所有path(i),那么修改就是树上路径求和,直接倍增预处理

首先路径条数做差分,也就是

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值