C. Propagating tree

Time Limit: 20 Sec

Memory Limit: 256 MB

题目连接

http://codeforces.com/contest/383/problem/C

Description

Iahub likes trees very much. Recently he discovered an interesting tree named propagating tree. The tree consists of n nodes numbered from 1 to n, each node i having an initial value ai. The root of the tree is node 1.

This tree has a special property: when a value val is added to a value of node i, the value -val is added to values of all the children of node i. Note that when you add value -val to a child of node i, you also add -(-val) to all children of the child of node i and so on. Look an example explanation to understand better how it works.

This tree supports two types of queries:

​ "1 x val" — val is added to the value of node x;

​ "2 x" — print the current value of node x.

In order to help Iahub understand the tree better, you must answer m queries of the preceding type.

Input

The first line contains two integers n and m (1 ≤ n, m ≤ 200000). The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 1000). Each of the next n–1 lines contains two integers vi and ui (1 ≤ vi, ui ≤ n), meaning that there is an edge between nodes vi and ui.

Each of the next m lines contains a query in the format described above. It is guaranteed that the following constraints hold for all queries: 1 ≤ x ≤ n, 1 ≤ val ≤ 1000.

Output

For each query of type two (print the value of node x) you must print the answer to the query on a separate line. The queries must be answered in the order given in the input.

Sample Input

5 5

1 2 1 1 2

1 2

1 3

2 4

2 5

1 2 3

1 1 2

2 1

2 2

2 4

Sample Output

3

3

0

HINT

题意

给出一颗有n个节点并一1为根节点的树,每个节点有它的权值,现在进行m次操作,操作分为添加和查询,当一个节点的权值添加val,则它的孩子节点的权值要添加-b。

题解:

方法一:dfs序+树状数组

学过或者没学过树链剖分的小朋友应该知道dfs序可以使得任意节点的子树变成一段连续的区间,这样就可以进行区间修改了。

但是这道题对子树层数的不同,操作也不一样,确实很麻烦呀。

我也是一脸懵逼,看完题解才发现原来如此神奇!!

其实我们可以把树分层,分成奇数层和偶数层(根据到根节点的距离),然后建两个树状数组,如果是对奇数层的点进行操作那么就给第一个树状数组相应的区间加上val,如果是偶数层就更新第二个树状数组。

这样对于某个节点i(假设是奇数层),那么此刻权值就是树状数组1-树状数组2。

感觉这种分层的思想很是神奇。

方法二:dfs序+线段树

第二天遇到另外一题 https://www.cnblogs.com/mmmqqdd/p/10844365.html ,突然发现这道题就是那题的简化版,大家可以先看看那题,

因为这道题用线段树实在是有点杀鸡用牛刀了,但是思想和不错哟。

我在这也简单的讲一下做法吧:

就是线段树每个节点都标记是奇数层还是偶数层,奇数层为-1,偶数层为1,然后如果处理奇数层就区间-val,偶数层就+val,其他的和线段树一样,最后求答案时,只要把最后的值×1或-1(奇数层-1,偶数层1)。

这个题目完全可以问一棵子数的权值和,这样像一棵正常的线段树了。

代码1--树状数组:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 400050
int n,m,cnt,w[N],a[N],c[2][N];
int dp[N],rk[N],kth[N],size[N];
int tot,last[N];
struct Edge{int from,to,s;}edges[N<<1];
template<typename T>void read(T&x)
{
ll k=0; char c=getchar();
x=0;
while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
if (c==EOF)exit(0);
while(isdigit(c))x=x*10+c-'0',c=getchar();
x=k?-x:x;
}
void read_char(char &c)
{while(!isalpha(c=getchar())&&c!=EOF);}
void AddEdge(int x,int y)
{
edges[++tot]=Edge{x,y,last[x]};
last[x]=tot;
}
void dfs(int x,int pre)
{
dp[x]=1-dp[pre];
rk[x]=++cnt;
kth[cnt]=x;
size[x]=1;
for(int i=last[x];i;i=edges[i].s)
{
Edge &e=edges[i];
if (e.to==pre)continue;
dfs(e.to,x);
size[x]+=size[e.to];
}
}
void update(int *c,int x,int tt)
{while(x<=n){c[x]+=tt;x+=x&-x;}}
int get_sum(int *c,int x)
{int ans=0;while(x){ans+=c[x];x-=x&-x;}return ans;}
int main()
{
#ifndef ONLINE_JUDGE
freopen("aa.in","r",stdin);
#endif
read(n);read(m);
for(int i=1;i<=n;i++)read(w[i]);
for(int i=1;i<=n-1;i++)
{
int x,y;
read(x); read(y);
AddEdge(x,y);
AddEdge(y,x);
}
dfs(1,0);
for(int i=1;i<=m;i++)
{
int id,x,val;
read(id);
if (id==1)
{
read(x); read(val);
update(c[dp[x]],rk[x],val);
update(c[dp[x]],rk[x]+size[x],-val);
}
if (id==2)
{
read(x);
int ans=get_sum(c[dp[x]],rk[x])-get_sum(c[1-dp[x]],rk[x]);
ans+=w[x];
printf("%d\n",ans);
}
} }

代码2--线段树:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 200050
int n,m,w[N];
int tot,last[N];
int cnt,rk[N],kth[N],d[N],size[N];
struct Tree{int l,r,c;}tr[N<<2];
struct Edge{int from,to,s;}edges[N<<1];
void AddEdge(int x,int y)
{
edges[++tot]=Edge{x,y,last[x]};
last[x]=tot;
}
template<typename T>void read(T&x)
{
ll k=0; char c=getchar();
x=0;
while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
if (c==EOF)exit(0);
while(isdigit(c))x=x*10+c-'0',c=getchar();
x=k?-x:x;
}
void read_char(char &c)
{while(!isalpha(c=getchar())&&c!=EOF);}
void dfs(int x,int pre)
{
rk[x]=++cnt;
kth[cnt]=x;
d[x]=-d[pre];
size[x]=1;
for(int i=last[x];i;i=edges[i].s)
{
Edge &e=edges[i];
if (e.to==pre)continue;
dfs(e.to,x);
size[x]+=size[e.to];
}
}
void push_down(int x)
{
Tree &a=tr[x<<1],&b=tr[x<<1|1];
a.c+=tr[x].c;
b.c+=tr[x].c;
tr[x].c=0;
}
void bt(int x,int l,int r)
{
tr[x].l=l; tr[x].r=r;
if (l==r) return;
int mid=(l+r)>>1;
bt(x<<1,l,mid);
bt(x<<1|1,mid+1,r);
}
void update(int x,int l,int r,int tt)
{
if (l<=tr[x].l&&tr[x].r<=r)
{tr[x].c+=tt;return;}
int mid=(tr[x].l+tr[x].r)>>1;
if (l<=mid)update(x<<1,l,r,tt);
if (mid<r)update(x<<1|1,l,r,tt);
}
int query(int x,int p)
{
if (p<=tr[x].l&&tr[x].r<=p)
return tr[x].c*d[kth[tr[x].l]];
int mid=(tr[x].l+tr[x].r)>>1;
push_down(x);
if (p<=mid)return query(x<<1,p);
else return query(x<<1|1,p);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("aa.in","r",stdin);
#endif
read(n); read(m);
for(int i=1;i<=n;i++)read(w[i]);
for(int i=1;i<=n-1;i++)
{
int x,y;
read(x); read(y);
AddEdge(x,y);
AddEdge(y,x);
}
d[0]=1;
dfs(1,0);
bt(1,1,n);
for(int i=1;i<=m;i++)
{
int id,x,tt;
read(id); read(x);
if (id==1)
{
read(tt);
update(1,rk[x],rk[x]+size[x]-1,tt*d[x]);
}
if (id==2)
printf("%d\n",w[x]+query(1,rk[x]));
}
}

Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+ 树状数组或线段树的更多相关文章

  1. Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组

    C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...

  2. Codeforces Round #225 (Div. 2) E. Propagating tree dfs序+-线段树

    题目链接:点击传送 E. Propagating tree time limit per test 2 seconds memory limit per test 256 megabytes inpu ...

  3. Codeforces Round #200 (Div. 1)D. Water Tree dfs序

    D. Water Tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/343/problem/ ...

  4. 343D/Codeforces Round #200 (Div. 1) D. Water Tree dfs序+数据结构

    D. Water Tree   Mad scientist Mike has constructed a rooted tree, which consists of n vertices. Each ...

  5. Codeforces 777E(离散化+dp+树状数组或线段树维护最大值)

    E. Hanoi Factory time limit per test 1 second memory limit per test 256 megabytes input standard inp ...

  6. Codeforces Round #535 (Div. 3) E2. Array and Segments (Hard version) 【区间更新 线段树】

    传送门:http://codeforces.com/contest/1108/problem/E2 E2. Array and Segments (Hard version) time limit p ...

  7. Codeforces Round #520 (Div. 2) E. Company(dfs序判断v是否在u的子树里+lca+线段树)

    https://codeforces.com/contest/1062/problem/E 题意 给一颗树n,然后q个询问,询问编号l~r的点,假设可以删除一个点,使得他们的最近公共祖先深度最大.每次 ...

  8. Codeforces Round #539 (Div. 1) C. Sasha and a Patient Friend 动态开点线段树

    题解看这里 liouzhou_101的博客园 更简洁的代码看这里: #include <bits/stdc++.h> using namespace std; typedef long l ...

  9. Codeforces Round #539 (Div. 1) 1109F. Sasha and Algorithm of Silence's Sounds LCT+线段树 (two pointers)

    题解请看 Felix-Lee的CSDN博客 写的很好,不过最后不用判断最小值是不是1,因为[i,i]只有一个点,一定满足条件,最小值一定是1. CODE 写完就A,刺激. #include <b ...

随机推荐

  1. 【CUDA 基础】6.2 并发内核执行

    title: [CUDA 基础]6.2 并发内核执行 categories: - CUDA - Freshman tags: - 流 - 事件 - 深度优先 - 广度优先 - 硬件工作队列 - 默认流 ...

  2. a a[0] &a &a[0]的理解

    数组中几个关键符号(a a[0] &a &a[0])的理解(前提是 int a[10])(1)这4个符号搞清楚了,数组相关的很多问题都有答案了.理解这些符号的时候要和左值右值结合起来, ...

  3. Django-安装/分组命名/路由分发

    一.安装Django 命令行窗口: pycharm安装: 二.创建Django项目 命令行窗口创建项目: 访问地址: 表示访问成功 注意如果我们在命令行窗口创建的应用需要我们手动的在django的se ...

  4. MyBatis动态Sql 的使用

    Mapper.xml提示: 1:mapper包中新建一个文件:mybatis-3-mapper.dtd 2:在web app libraries/mybatis.jar/org.apache.ibat ...

  5. HTML5 烟花系统

    需求:在一个虚拟烟花球中,在不同的部位填充不同颜色.质地的烟花火药:观看试放效果.最好能结合点物理学定律(以便展现火药粉被爆炸扩散到一定程度再爆炸的效果) 这是这学期的一个作业,感觉挺无聊的,纯粹是老 ...

  6. GIT管理以及运行规范

    继前天看分享的前后端分离后,又重新研究了GIT分支与各个环境的应用. 从开始使用git就一直有在网上查各种资料,查他的运行规范.但不知道是自己理解不够还是怎么的,一直用得不是很好. 根据自己的摸索,整 ...

  7. ERROR 1292(22007)

    ERROR 1292(22007) Table of Contents 1. 1292 1.1. 22007 1 1292   1.1 22007 错误信息 ERROR 1292 (22007): T ...

  8. 001-软件架构概览、maven补充【分包工程、合并包、web容器插件】、git补充

    一.整体概述 1.1.共性问题 技术瓶颈.不成体系.不能实际使用.不能落地.无法入门 1.2.目标-软件架构 专注于构建:高可扩展.高性能.大数据量.高并发.分布式的系统架构. 各项技术.组合构建分布 ...

  9. 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_6-2.申请微信支付介绍和不同场景的支付方式

    笔记 2.申请微信支付介绍和不同场景的支付方式         简介:介绍微信商户平台,支付方式和使用场景,申请微信支付流程                  1.什么是微信商户平台:        ...

  10. requestLibrary API

    requestLibrary API Keyword Arguments Documentation Create Ntlm Session alias, url, auth, headers={}, ...