CF 396C On Changing Tree(线段树)
来源:互联网 发布:淘宝帐号注销 编辑:程序博客网 时间:2024/05/16 05:07
题意:给出一棵树,最开始每个节点权值都为0,有两种操作,一种是将点v加上x,对于它的子树中的点,加上x-i*k,i为该点到v的距离,第二个是查询点v的值。
思路:通过dfs,可以把树转化为一个区间[l,r],第一种操作实际上是x+k*(dep[v]-dep[u]),dep[]为该点到根节点的距离,u为v的子树。那么我们用两个线段树维护x+k*dep[v]和k的值,查询时两个值用第一个值减去第二个值×dep[v]就是结果了。
代码:
#include <iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=300000+10;const int mod=1000000000+7;struct SegTree{ ll sum[maxn<<2],addv[maxn<<2]; void PushUp(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void PushDown(int l,int r,int rt) { if(addv[rt]) { int m=(l+r)>>1; addv[rt<<1]=(addv[rt<<1]+addv[rt])%mod; addv[rt<<1|1]=(addv[rt<<1|1]+addv[rt])%mod; sum[rt<<1]=(sum[rt<<1]+(m-l+1)*addv[rt])%mod; sum[rt<<1|1]=(sum[rt<<1|1]+(r-m)*addv[rt])%mod; addv[rt]=0; } } void build(int l,int r,int rt) { sum[rt]=addv[rt]=0; if(l==r) return ; int m=(l+r)>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); } ll Query(int L,int R,int l,int r,int rt) { if(l>=L&&r<=R) return sum[rt]; PushDown(l,r,rt); int m=(l+r)>>1; ll sum=0; if(m>=L) sum+=Query(L,R,l,m,rt<<1); if(m<R) sum+=Query(L,R,m+1,r,rt<<1|1); return sum%mod; } void Update(int L,int R,int l,int r,int rt,ll v) { if(l>=L&&r<=R) { addv[rt]=(addv[rt]+v)%mod; sum[rt]=(sum[rt]+(r-l+1)*v)%mod; return; } PushDown(l,r,rt); int m=(l+r)>>1; if(m>=L) Update(L,R,l,m,rt<<1,v); if(m<R) Update(L,R,m+1,r,rt<<1|1,v); PushUp(rt); }}t1,t2;struct Edge{ int v,next; Edge(){} Edge(int v,int next):v(v),next(next){}}edges[maxn<<1];int head[maxn],d[maxn],l[maxn],r[maxn],nEdge,dfs_clock;int n,q;void AddEdges(int u,int v){ edges[++nEdge]=Edge(v,head[u]); head[u]=nEdge; edges[++nEdge]=Edge(u,head[v]); head[v]=nEdge;}void Init(){ memset(head,0xff,sizeof(head)); nEdge=-1;dfs_clock=0; d[1]=0; t1.build(1,n,1); t2.build(1,n,1);}void dfs(int u,int fa){ l[u]=++dfs_clock; for(int k=head[u];k!=-1;k=edges[k].next) { int v=edges[k].v; if(v==fa) continue; d[v]=d[u]+1; dfs(v,u); } r[u]=dfs_clock;}int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); scanf("%d",&n); Init(); int type,v,x,k; for(int i=2;i<=n;++i) { scanf("%d",&v); AddEdges(i,v); } dfs(1,-1); scanf("%d",&q); while(q--) { scanf("%d",&type); if(type==1) { scanf("%d%d%d",&v,&x,&k); t1.Update(l[v],r[v],1,n,1,x+(ll)k*d[v]%mod); t2.Update(l[v],r[v],1,n,1,k); } else { scanf("%d",&v); ll ans=t1.Query(l[v],l[v],1,n,1); ans-=t2.Query(l[v],l[v],1,n,1)*d[v]; ans=(ans%mod+mod)%mod; printf("%I64d\n",ans); } } return 0;}
0 0
- CF 396C On Changing Tree(线段树)
- Codeforces Round 232 Div 1 C On Changing Tree 树状数组 或 线段树
- Codeforces 396C On Changing Tree(树状数组)
- codeforces 396C On Changing Tree dfs序+BIT
- CodeForces - 396C On Changing Tree(树状数组)
- CF 232 div2 E On Changing Tree 树状数组
- CF 383C Propagating tree(dfs序+线段树)
- cf#ecr7-C. Not Equal on a Segment-线段树-rmq
- Codeforces Round #232 (Div. 1) C. On Changing Tree(树上修改一点x-di*k))
- CF-Div2-207-C题+线段树
- CF 458C - Elections (枚举 + 线段树)
- CF - 718C 线段树+矩阵
- 通信 dsu on tree+线段树
- CF 242E XOR on Segment 【线段树】
- CF 242E XOR on Segment(二维线段树)
- CF 258E Little Elephant and Tree(DFS+线段树)
- CF 109C: Lucky Tree
- CF 431C k-Tree
- 有些高度,是真的到不了的
- 基于powerpc的uboot启动之硬件配置字问题
- 丰富的笔面试经验2---少年仍需努力(EDN)
- POJ 3368 Frequent values (UVA 11235)(RMQ)
- GoogleHTML编码规范15条
- CF 396C On Changing Tree(线段树)
- 设置直接进入二级页面流程以及log输出
- Home
- Nyoj-366 D的小L (全排列函数next_permutation的应用)
- Linux下SSH命令使用方法详解
- 【结构体】项目二。胖子伤不起
- Hibernate各种主键生成策略与配置详解
- 输入字符串以及输出
- HTML如何创建二级目录