CodeForces 396C On Changing Tree
2015-09-06 11:37
651 查看
On Changing Tree
Time Limit: 2000msMemory Limit: 262144KB
This problem will be judged on CodeForces. Original ID: 396C
64-bit integer IO format: %I64d Java class name: (Any)
You are given a rooted tree consisting of n vertices numbered from 1 to n. The root of the tree is a vertex number 1.
Initially all vertices contain number 0. Then come q queries, each query has one of the two types:
The format of the query: 1 v x k. In response to the query, you need to add to the number at vertex v number x; to the numbers at the descendants of vertex v at distance 1, addx - k; and so on, to the numbers written in the descendants of vertex v at distance i, you need to add x - (i·k). The distance between two vertices is the number of edges in the shortest path between these vertices.
The format of the query: 2 v. In reply to the query you should print the number written in vertex v modulo 1000000007 (109 + 7).
Process the queries given in the input.
Input
The first line contains integer n (1 ≤ n ≤ 3·105) — the number of vertices in the tree. The second line contains n - 1 integers p2, p3, ... pn (1 ≤ pi < i), where pi is the number of the vertex that is the parent of vertex i in the tree.The third line contains integer q (1 ≤ q ≤ 3·105) — the number of queries. Next q lines contain the queries, one per line. The first number in the line is type. It represents the type of the query. If type = 1, then next follow space-separated integers v, x, k (1 ≤ v ≤ n; 0 ≤ x < 109 + 7; 0 ≤ k < 109 + 7). If type = 2, then next follows integer v (1 ≤ v ≤ n) — the vertex where you need to find the value of the number.
Output
For each query of the second type print on a single line the number written in the vertex from the query. Print the number modulo 1000000007 (109 + 7).Sample Input
Input3 1 1 3 1 1 2 1 2 1 2 2
Output
2 1
Hint
You can read about a rooted tree here: http://en.wikipedia.org/wiki/Tree_(graph_theory).Source
Codeforces Round #232 (Div. 1)解题:树状数组或者线段树
给出一棵以1为根的树,形式是从节点2开始给出每个节点的父亲节点;
然后是m次操作,操作分为两种,1 v, x, k,表示在以v为根的字数上添加,添加的法则是看这个节点与v节点的距离为i的话,加上x-i*k;
2 v查询节点v的值。
发现相加的性质,维护两个树状数组
给c1 结点代表的区间都加上x + d[u]*k 给第二个树状数组也加上 d[u]*k
假设u是v的父节点 当计算v的时候 可以用$ x + d[u]*k - d[v]*k $
正是我们要的$x + k\times (d[u] - d[v])$
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn = 300010; const int mod = 1000000007; vector<int>g[maxn]; LL c[2][maxn],val[2]; int n,m,L[maxn],R[maxn],d[maxn],clk; void update(int i){ while(i < maxn){ c[0][i] += val[0]; c[1][i] += val[1]; c[0][i] %= mod; c[1][i] %= mod; i += i&-i; } } LL query(int i){ LL sum[2] = {0},dep = d[i]; i = L[i]; while(i > 0){ sum[0] += c[0][i]; sum[1] += c[1][i]; sum[0] %= mod; sum[1] %= mod; i -= i&-i; } return ((sum[0] - dep*sum[1])%mod + mod)%mod; } void dfs(int u,int dep){ L[u] = ++clk; d[u] = dep; for(int i = g[u].size()-1; i >= 0; --i) dfs(g[u][i],dep+1); R[u] = clk; } int main(){ int u,op,x,y,z; while(~scanf("%d",&n)){ for(int i = clk = 0; i <= n; ++i) g[i].clear(); for(int i = 2; i <= n; ++i){ scanf("%d",&u); g[u].push_back(i); } dfs(1,0); memset(c,0,sizeof c); scanf("%d",&m); while(m--){ scanf("%d%d",&op,&x); if(op == 1){ scanf("%d%d",&y,&z); val[0] = ((LL)y + (LL)d[x]*z)%mod; val[1] = z; update(L[x]); val[0] = -val[0]; val[1] = -val[1]; update(R[x]+1); }else printf("%I64d\n",query(x)); } } return 0; }
View Code
相关文章推荐
- [LeetCode] Longest Substring with At Most Two Distinct Characters
- Can't use Subversion command line client: svn和Errors found while svn working copies detection
- 基础知识
- List of devices attached 下无设备列表
- Unix/Linux僵尸进程
- DataGridView调整列宽
- Oracle定时调用存储过程
- std::deque
- Eclipse环境下a class file was not written问题的解决办法
- 利用Gson和SharePreference存储结构化数据
- usaco Overfencing
- $.ajax()
- jquery动态导航插件dynamicNav用法实例分析
- 轻松用python实现排列组合功能
- 年轻的采访可以学到很多东西
- java生成随机六位数的验证码&随机生成十位数ValidCode码,用于邮件的验证&检查是不是符合为合法的中国的手机号码
- VB6 padleft padright
- iOS textField详细解析(转)
- MySQL-版本不一致
- Android开发之获取相册照片和获取拍照照片