这个题多了一个操作难度直线上升,看完题解才会写

有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

按照题意:记录其DFS序,然后进栈是正,出栈为负,利用线段树进行更新

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <vector>
#include <stack>
using namespace std;
typedef long long LL;
const int N = ;
struct Edge
{
int v,next;
} edge[N<<];
int head[N],tot,cnt;
int val[N];
int in[N],out[N];
LL tree[N<<],lazy[N<<],seg[N];
int flag[N<<];
int io[N];
void addEdge(int u,int v)
{
edge[tot].v = v,edge[tot].next = head[u],head[u] = tot++;
}
void init()
{
memset(head,-,sizeof(head));
memset(val,,sizeof(val));
memset(lazy,,sizeof(lazy));
memset(io,,sizeof(io));
memset(seg,,sizeof(seg));
tot = cnt = ;
}
void dfs(int u,int fa)
{
seg[in[u] = ++cnt] = (LL)val[u];
io[cnt] = ;
for(int i=head[u]; i!=-; i=edge[i].next)
{
if(edge[i].v != fa)
{
dfs(edge[i].v,u);
}
}
seg[out[u] = ++cnt] = (LL)(-val[u]);
io[cnt] = -;
} void pushup(int idx)
{
tree[idx] = tree[idx<<]+tree[idx<<|];
return;
}
void pushdown(int idx)
{
if(lazy[idx])
{
tree[idx << ] += flag[idx<<]*lazy[idx];
tree[idx << | ] += flag[idx<<|]*lazy[idx];
lazy[idx << ] += lazy[idx];
lazy[idx << | ] += lazy[idx];
lazy[idx] = ;
}
return;
}
void build(int l,int r,int idx)
{
if(l==r)
{
tree[idx] = seg[l];
if(io[l]>) flag[idx] = ;
else flag[idx] = -;
return;
}
int mid = (l+r)>>;
build(l,mid,idx<<);
build(mid+,r,idx<<|);
pushup(idx);
flag[idx] = flag[idx<<] + flag[idx<<|];
}
void update(int l,int r,int L,int R,int idx,int val)
{
if(l>=L&&r<=R)
{
tree[idx] =tree[idx] + (LL)flag[idx]*val;
lazy[idx] =lazy[idx] + (LL)val;
return;
}
int mid = (l+r)>>;
pushdown(idx);
if(mid>=L) update(l,mid,L,R,idx<<,val);
if(mid<R) update(mid+,r,L,R,idx<<|,val);
pushup(idx);
}
LL query(int l,int r,int L,int R,int idx){
if(l>=L&&r<=R)
{
return tree[idx];
}
int mid = (l+r)>>;
LL sum = ;
pushdown(idx);
if(mid>=L) sum+=query(l,mid,L,R,idx<<);
if(mid<R) sum+=query(mid+,r,L,R,idx<<|);
return sum;
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(int i=; i<=n; i++)
{
scanf("%d",&val[i]);
}
for(int i=; i<n; i++)
{
int u,v;
scanf("%d%d",&u,&v);
addEdge(u,v);
addEdge(v,u);
}
dfs(,);
build(,*n,);
while(m--)
{
int op,x,y;
scanf("%d",&op);
if(op==)
{
scanf("%d%d",&x,&y);
update(,*n,in[x],in[x],,y);
update(,*n,out[x],out[x],,y);
}else if(op==){
scanf("%d%d",&x,&y);
update(,*n,in[x],out[x],,y);
}else{
scanf("%d",&x);
LL sum = query(,*n,,in[x],);
printf("%lld\n",sum);
}
}
}
}

bzoj 4034(DFS序+线段树)的更多相关文章

  1. BZOJ 1103 DFS序+线段树

    思路: 先搞出来DFS序 进入这个点 +1 出这个点 -1 线段树维护前缀和 (因为还要修改) 搞定 修改的时候只修改底下节点就OK了 (边权–>点权 不多说) //By SiriusRen # ...

  2. BZOJ 2819 DFS序+线段树

    非递归的DFS写炸了- 交了一个递归版的 过了---.. //By SiriusRen #include <cstdio> #include <cstring> #includ ...

  3. DFS序+线段树(bzoj 4034)

    题目链接 题目就不多说了. 本题目,可以用dfs序+线段树做:题目给定了一棵树,树上节点告诉了权值.我们可以先将这棵树进行dfs将一棵树变成线性结构:如图 变成这样后,然后就可以用线段树. 操作1:也 ...

  4. BZOJ 3252题解(贪心+dfs序+线段树)

    题面 传送门 分析 此题做法很多,树形DP,DFS序+线段树,树链剖分都可以做 这里给出DFS序+线段树的代码 我们用线段树维护到根节点路径上节点权值之和的最大值,以及取到最大值的节点编号x 每次从根 ...

  5. Educational Codeforces Round 6 E dfs序+线段树

    题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...

  6. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] D ...

  7. Codeforces 343D Water Tree(DFS序 + 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

  8. BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)

    题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...

  9. POJ 3321 DFS序+线段树

    单点修改树中某个节点,查询子树的性质.DFS序 子树序列一定在父节点的DFS序列之内,所以可以用线段树维护. 1: /* 2: DFS序 +线段树 3: */ 4:   5: #include < ...

随机推荐

  1. 语法:c++对关于空指针0/NULL/nullptr三者的演变

    来源: https://blog.csdn.net/u010558281/article/details/77793644 字面意义上的解释: 0:整型常量 NULL:预处理符号 nullptr:空指 ...

  2. centos7 U盘安装卡在 starting dracut initqueue hook解决办法

    U盘安装centos7启动过程中出现: [ok] Reached target Basic System 或者 [ok] starting dracut initqueue hook   到下一行就不 ...

  3. [Leetcode] Backtracking回溯法解题思路

    碎碎念: 最近终于开始刷middle的题了,对于我这个小渣渣确实有点难度,经常一两个小时写出一道题来.在开始写的几道题中,发现大神在discuss中用到回溯法(Backtracking)的概率明显增大 ...

  4. 并发库应用之三 & 线程池与定时器应用

    在TCP服务器编程模型的原理,每一个客户端连接用一个单独的线程为之服务,当与客户端的会话结束时,线程也就结束了,即每来一个客户端连接,服务器端就要创建一个新线程.如果访问服务器的客户端很多,那么服务器 ...

  5. UDP_TCP示意图

  6. day19 IO编程

    文件:文件是数据源(保存数据的地方)的一种. 文件在程序中是以流的形式来操作的 内存(程序)到文件是输出流,文件到内存(程序)是输入流. 字节流:可用于读写的二进制文件及任何类型文件. 字符流:可以用 ...

  7. python---基础知识回顾(十)进程和线程(多线程)

    前戏:多线程了解 使用多线程处理技术,可以有效的实现程序并发,优化处理能力.虽然进程也可以在独立的内存空间并发执行,但是生成一个新的进程必须为其分配独立的地址空间,并维护其代码段,堆栈段和数据段等,这 ...

  8. 记录第一次阿里云服务器部署java web工程的经历

    起因:测试一个微信小程序,发现所有的请求要求为https的形式,开发工具忽略后手机无法测试,故尝试配置. 准备:阿里云服务器一台 域名一个(解析在服务器)     tomcat7.0.54     j ...

  9. IntelliJ IDEA连接cvs超时Error refreshing view: Timeout while trying to connect to host

    在使用IntelliJ IDEA连接cvs的时候,有时会报超时错误: Error refreshing view: Timeout while trying to connect to host: 1 ...

  10. Uva 11549 - Calculator Conundrum 找规律加map

    题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...