第八届福建省大学生程序设计竞赛 FZU 2277 Change (dfs序+树状数组)
来源:互联网 发布:mysql修复表命令 编辑:程序博客网 时间:2024/06/05 20:42
题目原文:
Accept: 60 Submit: 354
Time Limit: 2000 mSec Memory Limit : 262144 KB
Problem Description
There is a rooted tree with n nodes, number from 1-n. Root’s number is 1.Each node has a value ai.
Initially all the node’s value is 0.
We have q operations. There are two kinds of operations.
1 v x k : a[v]+=x , a[v’]+=x-k (v’ is child of v) , a[v’’]+=x-2*k (v’’ is child of v’) and so on.
2 v : Output a[v] mod 1000000007(10^9 + 7).
Input
First line contains an integer T (1 ≤ T ≤ 3), represents there are T test cases.
In each test case:
The first line contains a number n.
The second line contains n-1 number, p2,p3,…,pn . pi is the father of i.
The third line contains a number q.
Next q lines, each line contains an operation. (“1 v x k” or “2 v”)
1 ≤ n ≤ 3*10^5
1 ≤ pi < i
1 ≤ q ≤ 3*10^5
1 ≤ v ≤ n; 0 ≤ x < 10^9 + 7; 0 ≤ k < 10^9 + 7
Output
For each operation 2, outputs the answer.
Sample Input
Sample Output
Source
第八届福建省大学生程序设计竞赛-重现赛(感谢承办方厦门理工学院)题目大意:有一棵树,初始状态下所有的节点权值都为0,有两种操作,第一种是选定这棵树的一个节点,然后把这个子树上的所有子节点都+x,然后再按照层数差,往下减k。
解题思路:
例如选定一棵以u节点为根节点的子树,v是这棵子树上的点。用dep[]数组来维护每个节点的深度。
那么一次更新操作相当于对 a[v] += x + (d[u] - d[v])*k 整理得 a[v] += (x + k*d[u] )- k*d[v] 红色部分对这个子树上的所有顶点是一个定值,可以用线段树或者树状数组维护。而后一部分的d[v]是每个节点的深度属性,无需维护,所以我们只需要再开一个树状数组/线段树来维护k的和。
通过对这两个量的维护我们就可以针对每一个询问得到想要的结果。
【注】最开始选择用线段树维护这两个值,但是一直TLE,应该是被卡了常数,即使加上了输入输出外挂也不能解决问题。后来选择树状数组来维护,一次AC,并且代码简洁,感觉这类区间更新,单点修改的题目比较适合使用树状数组来解决。
AC代码:
//区间修改 单点查询#include <vector>#include <list>#include <map>#include <set>#include <queue>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iostream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <ctime>#include <cstring>#include <limits>#include <climits>#include <cstdio>#define Fori(x) for(int i=0;i<x;i++)#define Forj(x) for(int j=0;j<x;j++)#define maxn 300007#define inf 0x3f3f3f3f#define pb push_back#define ONES(x) __builtin_popcount(x)#define _ << " " <<using namespace std;typedef long long ll ;const double eps =1e-8;const int mod = 1000000007;typedef pair<int, int> P;const double PI = acos(-1.0);int dx[4] = {0,0,1,-1};int dy[4] = {1,-1,0,0};inline int read(){ int data=0,w=1; char ch=0; while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar(); if(ch=='-') w=-1,ch=getchar(); while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar(); return data*w;}inline ll readll(){ ll data=0; int w=1; char ch=0; while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar(); if(ch=='-') w=-1,ch=getchar(); while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar(); return data*w;}inline void write(int x){ if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0');}inline void writell(ll x){ if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0');}vector<int> e[maxn];int v;ll x,k;int n;int step;int in[maxn],out[maxn];//in out 维护出入时间戳int dep[maxn];//维护深度void dfs(int u,int fa,int depth){ in[u]=step++; dep[u]=depth; for(int i=0;i<e[u].size();i++) { int v = e[u][i]; if(v==fa) continue; dfs(v,u,depth+1); } out[u]=step-1;}//BIT 向下统计 向上修改ll bit[maxn];ll bit1[maxn];ll sum(ll *bit , int i){ ll s = 0; while(i>0){ s = (s + bit[i])%mod; i -= i & -i; } return s;}void add(ll *bit , int i, ll x)//i 不能取 0{ while(i<=n){ bit[i] = (bit[i] + x)%mod; i += i&-i; }}int main(){ int t; scanf("%d",&t); while(t--) { n=read(); step=1; for(int i = 1; i<=n; i++) e[i].clear(); for(int i = 2; i<=n; i++){ int p = read(); e[p].pb(i); } dfs(1,-1,1); int q = read(); for(int i = 0; i<maxn-2; i++) bit[i] = bit1[i] = 0; while(q--) { int type = read(); if(type==1) { v=read(); x=readll(); k=readll(); ll A=(x+k*dep[v])%mod; add(bit,in[v],A); add(bit,out[v]+1,-A); //update(1,in[v],out[v],A); //update1(1,in[v],out[v],k); add(bit1,in[v],k); add(bit1,out[v]+1,-k); } else { v=read(); //ll A=query(1,in[v],in[v]); //ll B=query1(1,in[v],in[v]); ll A = sum(bit,in[v]); ll B = sum(bit1,in[v]); ll ans=((A-B*dep[v])%mod+mod)%mod; writell(ans); printf("\n"); } } } return 0;}
- 第八届福建省大学生程序设计竞赛 FZU 2277 Change (dfs序+树状数组)
- 第八届福建省大学生程序设计竞赛-重现赛(F Problem 2277 Change)DFS序+树状数组
- fzu 2277 Change [第八届福建省大学生程序设计竞赛 Problem F] [线段树]
- 第八届福建省大学生程序设计竞赛
- FZU Problem 2216 The Longest Straight(二分答案+树状数组)——第六届福建省大学生程序设计竞赛-重现赛
- fzu 2278 YYS [第八届福建省大学生程序设计竞赛 Problem G] [概率]
- fzu 2275 Game [第八届福建省大学生程序设计竞赛 Problem D] [字符串匹配]
- 第八届福建省大学生程序设计竞赛 FZU 2273 Triangles (计算几何)
- fzu 2281 Trades [第八届福建省大学生程序设计竞赛 Problem J Trades] [贪心]
- 2017第八届福建省大学生程序设计竞赛总结
- 第八届福建省大学生程序设计竞赛训练总结【7/12】
- 第八届福建省大学生程序设计竞赛 D.Game【思维+KMP】
- 第八届福建省大学生程序设计竞赛-重现赛 A Frog
- 第八届福建省大学生程序设计竞赛-重现赛I Magic
- 7.22.17 第八届福建省大学生程序设计竞赛-重现赛
- 第八届福建省大学生程序设计竞赛 G.YYS【期望+大数】
- FZU2272+Frog+签到题+第八届福建省大学生程序设计竞赛
- FZU2273Triangles+(三角形)+第八届福建省大学生程序设计竞赛
- iOS UserDefaults存储自定义对象
- 联合体(union)的使用方法及其本质
- ZK框架的分析与应用
- mysql游标
- 算法系列——Copy List with Random Pointer
- 第八届福建省大学生程序设计竞赛 FZU 2277 Change (dfs序+树状数组)
- 父类指针强制转换为子类指针
- 同步与异步
- c++构造函数,函数重载,复合类,类和对象
- python中sqlite3对数据库的增删改查
- android按分辨率压缩图片
- 页面处理特殊字符传输
- 多线程处理list业务逻辑(大数量)
- android自定义View,区域热力地图(具备每个省份的点击接口)