bzoj 4034(DFS序+线段树)
这个题多了一个操作难度直线上升,看完题解才会写
有一棵点数为 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序+线段树)的更多相关文章
- BZOJ 1103 DFS序+线段树
思路: 先搞出来DFS序 进入这个点 +1 出这个点 -1 线段树维护前缀和 (因为还要修改) 搞定 修改的时候只修改底下节点就OK了 (边权–>点权 不多说) //By SiriusRen # ...
- BZOJ 2819 DFS序+线段树
非递归的DFS写炸了- 交了一个递归版的 过了---.. //By SiriusRen #include <cstdio> #include <cstring> #includ ...
- DFS序+线段树(bzoj 4034)
题目链接 题目就不多说了. 本题目,可以用dfs序+线段树做:题目给定了一棵树,树上节点告诉了权值.我们可以先将这棵树进行dfs将一棵树变成线性结构:如图 变成这样后,然后就可以用线段树. 操作1:也 ...
- BZOJ 3252题解(贪心+dfs序+线段树)
题面 传送门 分析 此题做法很多,树形DP,DFS序+线段树,树链剖分都可以做 这里给出DFS序+线段树的代码 我们用线段树维护到根节点路径上节点权值之和的最大值,以及取到最大值的节点编号x 每次从根 ...
- Educational Codeforces Round 6 E dfs序+线段树
题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...
- 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心
3252: 攻略 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 339 Solved: 130[Submit][Status][Discuss] D ...
- Codeforces 343D Water Tree(DFS序 + 线段树)
题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...
- BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)
题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...
- POJ 3321 DFS序+线段树
单点修改树中某个节点,查询子树的性质.DFS序 子树序列一定在父节点的DFS序列之内,所以可以用线段树维护. 1: /* 2: DFS序 +线段树 3: */ 4: 5: #include < ...
随机推荐
- Python word_cloud 部分文档翻译 标签云系列(二)
转载地址:https://zhuanlan.zhihu.com/p/20436581上文末尾提到 Python 下还有一款词云生成器.amueller/word_cloud · GitHub 可以直接 ...
- micro 架构组件介绍
Micro 是什么 Micro 是微服务生态系统中专注于提供产品.服务和解决方案的一款软件,使得在现代软件企业中起到创新驱动.它计划是可以将任何微服务相关的资源与即将使用此款软件的公司结合起来,利用此 ...
- P4889 kls与flag
P4889 kls与flag 一堆杆子, 每个有特定高度 \(a_{i}\) , 现想把杆子弄倒, 可以在一维内往左弄倒和往右弄倒, 求最大优秀对数, 定义优秀对数为两杆倒后顶点重合 Solution ...
- windows配置Python多版本共存
windows配置Python多版本共存 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 最近Python开发蛮火的,三年前我的一个运维朋友就告诉我说Python语言将来会很火,当时 ...
- Java基础-Collection子接口之Set接口
Java基础-Collection子接口之Set接口 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 学习Collection接口时,记得Collection中可以存放重复元素,也可 ...
- day7 方法及基础知识运用
做了一个小型的成绩管理系统.主要代码如下: /* * 功能:简易学生成绩管理系统 */package day7; import java.util.Scanner; public class Home ...
- Matlab周期图法使用FFT实现
参考文章:http://www.cnblogs.com/adgk07/p/9314892.html 首先根据他这个代码和我之前手上已经拥有的那个代码,编写了一个适合自己的代码. 首先模仿他的代码,测试 ...
- css选择器 nth-child
html代码: <div> <p>多云转晴</p> <p>多云转晴</p> <p>多云转晴</p> <p> ...
- Shell记录-Shell命令(磁盘)
inux中df命令的功能是用来检查linux服务器的文件系统的磁盘空间占用情况.可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信息. 1.命令格式 df [选项] [文件] Shell ...
- mongo ttl索引
db.log_events.find() # 查找log_events里的所有数据 db.log_events.create ...