昨天的CF自己太挫了。一上来看到A题,就有思路,然后马上敲,但是苦于自己很久没有敲计数的题了,许多函数都稍微回忆了一阵子。A题的主要做法就是将每个数质因数分解,统计每个质因子的个数,对于每个质因子pi的个数k,等价于解一个方程x1+x2+...+xn=k的有多少个非负整数解,学过离散数学或者一些组合数学的就会知道,答案是C(k,n+k-1),但是由于n+k-1可能会很大,我一开始考虑小了,贡献了好多次RE,所以在算组合数的时候只能算出每个数的阶乘以及对应的逆元去算,然后将每个因子算出来的结果乘起来就可以了。

B的话写一下就会发现很明显的能够裂项,所以问题就转换成求u(n),v(n),n的大小达到10^9,但是基于素数的稠密性我们可以在有限的时间内算出来,10^11以内的相邻素数间隔貌似是在400多还是500多,每次判素数的复杂度是根号n,所以大致找出u(n),v(n)的时间是在10^7以内,这个在CF上绝对是可以算的,知道u,v后面的就是简单的计算一下。当然为了加快速度,可以考虑素性测试。

C的话拿到的时候时间不多了,想了一下就有了思路,但是10分钟真的打不出来,于是就想想算了。今天才打出来的。在树上对结点以及它的后代进行更新自然是先把这棵树搜成dfs序列,但是像题目这种,隔一层-k的怎么办呢? 可以考虑建两棵线段树,首先预处理出每棵树的深度dep,每次更新的时候就在第一棵线段树上每个结点加上x+k*dep[v],然后再在第二棵线段树上加上-k。 那么询问的时候怎么办呢? 询问的时候的答案就是 该结点在第一棵线段树上的值ans1,加上在第二棵线段树上的值ans2乘上对应结点的深度 即 ans1+ans2*dep[v]。可以优化的地方是其实并不需要建两棵,只是一棵线段数维护两个值而已,我写的这份代码很慢,1.9s,差不多都超时了,不过也没有办法啦。

#pragma warning(disable:4996)
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<cmath>
#include<map>
#define maxn 300500
#define ll long long
#define mod 1000000007
using namespace std;struct Node
{int l, r;ll add, sum;
};struct SegmentTree
{Node N[4 * maxn];void build(int i, int L, int R){N[i].l = L; N[i].r = R; N[i].sum = N[i].add = 0;if (L == R){return;}int M = (L + R) >> 1;build(i << 1, L, M);build(i << 1 | 1, M + 1, R);}void pushDown(int i){ll tt = N[i].add;if (N[i].l == N[i].r) return;if (tt != 0){(N[i << 1].add += tt) %= mod;(N[i << 1 | 1].add += tt) %= mod;(N[i << 1].sum += (N[i << 1].r - N[i << 1].l + 1)*tt%mod) %= mod;(N[i << 1 | 1].sum += (N[i << 1 | 1].r - N[i << 1 | 1].l + 1)*tt%mod) %= mod;N[i].add = 0;}}void pushUp(int i){N[i].sum = (N[i << 1].sum + N[i << 1 | 1].sum) % mod;}void add(int i, int L, int R, ll s){if (N[i].l == L&&N[i].r == R){(N[i].add += s) %= mod;(N[i].sum += (R - L + 1)*s) %= mod;return;}pushDown(i);int M = (N[i].l + N[i].r) >> 1;if (R <= M) add(i << 1, L, R, s);else if (L > M) add(i << 1 | 1, L, R, s);else add(i << 1, L, M, s), add(i << 1 | 1, M + 1, R, s);pushUp(i);}ll query(int i, int L, int R){if (N[i].l == L&&N[i].r == R){return N[i].sum;}pushDown(i);int M = (N[i].l + N[i].r) >> 1;if (R <= M) return query(i << 1, L, R);else if (L > M) return query(i << 1 | 1, L, R);else return query(i << 1, L, M) + query(i << 1 | 1, M + 1, R);//pushUp(i);}
}st[2];int n;
vector<int> G[maxn];
int dep[maxn];
int pre[maxn];
int post[maxn];
int dfs_clock;void dfs(int u, int fa,int d)
{pre[u] = ++dfs_clock;dep[u] = d;for (int i = 0; i < G[u].size(); i++){int v = G[u][i];if (v == fa) continue;dfs(v, u, d + 1);}post[u] = dfs_clock;
}int main()
{while (cin >> n){for (int i = 0; i <= n; i++) G[i].clear();int vi;for (int i = 2; i <= n; i++){scanf("%d", &vi);G[vi].push_back(i);G[i].push_back(vi);}dfs_clock = 0;dfs(1, -1, 0);st[0].build(1, 1, n); st[1].build(1, 1, n);int q; scanf("%d", &q);ll vq, xq, kq;int tq;for (int i = 0; i < q; i++){scanf("%d", &tq);if (tq == 1){scanf("%I64d%I64d%I64d", &vq, &xq, &kq);st[0].add(1, pre[vq], post[vq], (xq + dep[vq] * kq)%mod);st[1].add(1, pre[vq], post[vq], -kq);}else{ll ans = 0; scanf("%d", &vq);ans = (ans + st[0].query(1, pre[vq], pre[vq])) % mod;ans = (ans + st[1].query(1, pre[vq], pre[vq])*dep[vq]) % mod;ans = (ans + mod) % mod;printf("%I64d\n", ans);}}}return 0;
}

转载于:https://www.cnblogs.com/chanme/p/3571783.html

CodeForces369C On Changing Tree相关推荐

  1. CF396C On Changing Tree

    CF396C On Changing Tree 给定一棵以 \(1\) 为根的树,初始时所有点权为 \(0\) 有 \(m\) 次操作,分为两种 \(1\ u\ x\ k\) 表示给以 \(u\) 的 ...

  2. ASP.NET 生命周期(原文翻译)

    在网上看到这篇文章,老外写的,里面很多图片挺精致,顺带翻译过来给大家分享下,英语太次好多地方都翻不过来 ASP.NET application and page life cycle Download ...

  3. 655. Print Binary Tree 解题报告(树)

    第一部分:搜索.遍历 [例子1]655. Print Binary Tree Example 1: Input:1/2 Output: [["", "1", & ...

  4. Recover Binary Search Tree

    Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...

  5. [leetcode] Recover Binary Search Tree

    Recover Binary Search Tree Two elements of a binary search tree (BST) are swapped by mistake. Recove ...

  6. 99. Recover Binary Search Tree (Tree; DFS)

    Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...

  7. Recover Binary Search Tree,恢复二叉排序树

    问题描述:题意就是二叉树中有两个节点交换了,恢复结构. Two elements of a binary search tree (BST) are swapped by mistake. Recov ...

  8. ALV TREE学习笔记

    在这一篇中将学习一下ALV Tree的使用方法.通过名字可以看出,ALV TREE应该是将ALV与TREE这两者进行组合. ALV Tree实现原理:创建一个 cl_gui_alv_tree对象,定义 ...

  9. Spark MLlib: Decision Tree源码分析

    http://spark.apache.org/docs/latest/mllib-decision-tree.html 以决策树作为开始,因为简单,而且也比较容易用到,当前的boosting或ran ...

最新文章

  1. php 多人游戏_「谁会是下一个王者农药」云服务器如何搭建游戏服务器?
  2. JZOJ 5407. 【NOIP2017提高A组集训10.21】Deep
  3. java8 lambda 视频_一文搞懂Java8 Lambda表达式(附带视频教程)
  4. 拼字符串成为时间,和两个计算时间点的中间值
  5. 程序员修神之路--分布式系统使用网关到底是好还是坏?
  6. win10使用docker desktop安装k8s一直starting解决方法
  7. 天池 在线编程 布尔表达式求值(栈)
  8. Maven学习总结(18)——深入理解Maven仓库
  9. Java多线程再理解(synchronized)
  10. Visual Studio 2012 激活码
  11. Android性能优化的问题
  12. 海信电视power android,海信电视工厂模式中“To Fac”设置“U”、“M”参数不完全对比...
  13. iPhone 邮件html设置,iphone手机邮件设置教程
  14. 老男孩第十四期Python学习班之Day02
  15. 内存 显存,cpu,GPU,显卡
  16. bootstrap-列表样式
  17. java ktv喝酒游戏
  18. MATLAB中cftool多曲线画图
  19. medium_socnet靶场
  20. 【机器人】无传感器的工业机器人负载估计

热门文章

  1. 夫妻两人同一个银行各自存50万,银行破产了该赔多少?
  2. [转] Windows CE 6.0 启动过程分析
  3. python堆排序求topn_Java堆排序,取得前TopN个数
  4. mysql数据库压缩备份_MySQL数据库之mysql数据库备份命令分享(mysql压缩数据库备份)...
  5. 所属的用户_关于chmod(变更用户对此文件的相关权限)超详细说明,小白秒懂
  6. 二阶偏微分方程组 龙格库塔法_有限单元法(Finite Element Method)实现声波方程模拟(Part 2)...
  7. 关于Django路由层简单笔记
  8. 在一个div里,列表样式图片进行float,实现水平排序
  9. RecyclerView(滚动控件)的用法
  10. automaticallyAdjustsScrollViewInsets的作用