题目

题目描述

有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:

  • 操作 1 :把某个节点 x 的点权增加 a 。
  • 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
  • 操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

输入格式

第一行包含两个整数 N, M 。表示点数和操作数。
接下来一行 N 个整数,表示树中节点的初始权值。
接下来 N-1 行每行两个正整数 from, to , 表示该树中存在一条边 (from, to) 。
再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。

输出格式

对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

输入输出样例

输入 #1复制

5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3

输出 #1复制

6
9
13

说明/提示

对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不会超过 10^6 。

分析

  • 首先,我们要知道dfs序
  • 就是一颗树进出栈的顺序
  • 然后我们记录下他们的时间戳
  • 就知道他们的左右子树在哪个区间
  • 然后用线段树维护
  • 还有一个重要的点是
  • 我们可以发现1-x点就是x进栈的前缀
  • 考虑如何维护线段树
  • 首先我们是有x和-x的,我们要一个前缀数组搞出区间正x的个数
  • 对于第一个修改x+=x -x+=-x就好了
  • 然后主要区间加一定打lazy
  • lazy的return 是如果数在区间里面的
  • 然后还有

    if (a<=mid) ans+=find(k<<1,a,b);
    if (b>=mid+1) ans+=find(k<<1|1,a,b); 别忘了

代码

  1 #include<iostream>
  2 #include<cstdio>
  3 #define ll long long
  4 using namespace std;
  5 ll a[500001];
  6 struct sb
  7 {
  8     ll l,r,sum,bz,add;
  9 }t[2*200001];
 10 ll id[500001],num,le[500001],ri[500001],vis[500001],ss[500001];
 11 struct node
 12 {
 13     ll to,nx;
 14 }g[2*200010];
 15 ll list[2*200010],cnt;
 16 void add(ll x,ll y)
 17 {
 18     g[++cnt].to=y; g[cnt].nx=list[x]; list[x]=cnt;
 19     g[++cnt].to=x; g[cnt].nx=list[y]; list[y]=cnt;
 20 }
 21 ll val[500001],v,flag[500001];
 22 inline ll read(){
 23     ll x=0,f=1;
 24     char ch=getchar();
 25     while(ch<'0'||ch>'9'){
 26         if(ch=='-')
 27             f=-1;
 28         ch=getchar();
 29     }
 30     while(ch>='0'&&ch<='9'){
 31         x=(x<<1)+(x<<3)+(ch^48);
 32         ch=getchar();
 33     }
 34     return x*f;
 35 }
 36 void dfs(ll x)
 37 {
 38     vis[x]=1;
 39     id[x]=++num;
 40     val[num]=a[x];
 41     flag[num]=1;
 42     le[x]=num;
 43     for (int i=list[x];i;i=g[i].nx)
 44     {
 45         ll y=g[i].to;
 46         if (!vis[y])
 47             dfs(y);
 48     }
 49     ri[x]=++num;
 50     val[num]=-a[x];
 51     flag[num]=-1;
 52 }
 53 void build(ll k,ll a,ll b)
 54 {
 55     t[k].l=a; t[k].r=b;
 56     if (a==b)
 57     {
 58         t[k].sum=val[a];
 59         t[k].bz=flag[a];
 60         return;
 61     }
 62     ll mid=a+b>>1;
 63     build(k<<1,a,mid);
 64     build(k<<1|1,mid+1,b);
 65     t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
 66     t[k].bz=t[k<<1].bz+t[k<<1|1].bz;
 67 }
 68 void change(ll k,ll mb,ll z)
 69 {
 70     t[k].sum+=z;
 71     if (t[k].l==t[k].r) return;
 72     ll mid=t[k].l+t[k].r>>1;
 73     if (mb<=mid) change(k<<1,mb,z);
 74     else change(k<<1|1,mb,z);
 75 }
 76 void lazy(ll k,ll a,ll b,ll m)
 77 {
 78     if (t[k].add!=0)
 79     {
 80         t[k<<1].add+=t[k].add;
 81         t[k<<1|1].add+=t[k].add;
 82         t[k<<1].sum=t[k<<1].sum+t[k].add*(ss[m]-ss[a-1]);
 83         t[k<<1|1].sum=t[k<<1|1].sum+t[k].add*(ss[b]-ss[m]);
 84         t[k].add=0;
 85     }
 86 }
 87 void change2(ll k,ll a,ll b,ll z)
 88 {
 89     if (a<=t[k].l&&b>=t[k].r)
 90     {
 91         t[k].add+=z;
 92         t[k].sum=t[k].sum+z*(ss[t[k].r]-ss[t[k].l-1]);
 93         return;
 94     }
 95     ll mid=(t[k].l+t[k].r)>>1;
 96     lazy(k,t[k].l,t[k].r,mid);
 97     if (a<=mid) change2(k<<1,a,b,z);
 98     if (b>=mid+1) change2(k<<1|1,a,b,z);
 99     t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
100 }
101 ll find(ll k,ll a,ll b)
102 {
103     if (t[k].l>=a&&t[k].r<=b)
104       return t[k].sum;
105     ll mid=t[k].l+t[k].r>>1;
106     ll ans=0;
107     lazy(k,t[k].l,t[k].r,mid);
108     if (a<=mid) ans+=find(k<<1,a,b);
109     if (b>=mid+1) ans+=find(k<<1|1,a,b);
110     return ans;
111 }
112 int main ()
113 {
114     ll n,m;
115     n=read(); m=read();
116     for (int i=1;i<=n;i++)
117       a[i]=read();
118     for (int i=1,x,y;i<=n-1;i++)
119     {
120         x=read(); y=read();
121         add(x,y);
122     }
123     dfs(1);
124     for (int i=1;i<=num;i++)
125       ss[i]=ss[i-1]+flag[i];
126     build(1,1,2*n);
127     for (int i=1,op,x,y;i<=m;i++)
128     {
129         op=read();
130         if (op==1)
131         {
132             x=read(); y=read();
133             change(1,le[x],y);
134             change(1,ri[x],-y);
135         }
136         if (op==2)
137         {
138             x=read(); y=read();
139             change2(1,le[x],ri[x],y);
140         }
141         if (op==3)
142         {
143             x=read();
144             printf("%lld\n",find(1,1,le[x]));
145         }
146     }
147 }

转载于:https://www.cnblogs.com/zjzjzj/p/11379377.html

luogu P3178 [HAOI2015]树上操作相关推荐

  1. P3178 [HAOI2015]树上操作

    P3178 [HAOI2015]树上操作 题意: 题解: 这已经是很裸的树链剖分了... 直接套模板 代码: #include<cmath> #include<cstdio> ...

  2. Luogu P3177 [HAOI2015] 树上染色(树上背包)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Luogu P3177 [HAOI2015] 树上染色 有一棵点数为 NNN 的树,树边有边权.给你一 ...

  3. BZOJ 4043 [HAOI2015]树上操作 dfs序 线段树

    $ \Rightarrow $ 戳我进BZOJ原题 $ \Rightarrow $ 戳我进洛谷原题 [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 25 ...

  4. bzoj 4034: [HAOI2015]树上操作(树链剖分+线段树区间更新)

    4034: [HAOI2015]树上操作 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 4981  Solved: 1603 [Submit][St ...

  5. [HAOI2015]树上操作

    题目大意: 给你一棵n个点的树,以1为根,每个点都有一个点权,要求进行如下操作: 1.将x这个点的点权加上a: 2.将以x这个点为根的子树中每个点的点权加上a: 3.查询从x到根的路径的点权和. 思路 ...

  6. bzoj4034: [HAOI2015]树上操作

    这题其实就是树剖裸题啊. 然后毒瘤选手由于上题树剖被卡到哭所以选择dfs序+树状数组. 不得不说简单的算法做出来更加难思考.然后网上的dalao们都一笔带过净说什么用两个树状数组维护就可以啦. 经过大 ...

  7. [BZOJ 4034][HAOI2015]树上操作(欧拉序列+线段树)

    Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中 ...

  8. 省选专练HAOI2015树上操作

    题如其名 树链剖分板子题 #include<bits/stdc++.h> using namespace std; #define lc (p<<1) #define rc ( ...

  9. [BZOJ4033][HAOI2015]树上染色

    4033: [HAOI2015]树上染色 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 2108  Solved: 901 [Submit][Sta ...

最新文章

  1. javascript数组降维_Javascript实现的数组降维——维度不同,怎么谈恋爱
  2. 比学习新技术更重要的是思维的改变
  3. android学习笔记:数据库存储
  4. Windows端口占用情况?
  5. bzoj 2330 糖果
  6. 随想录(fatfs的学习)
  7. 按照这个步骤来刷题,迷茫的你两个月亦能成为王者
  8. Git 协同开发流程
  9. Android 常用adb shell 命令
  10. spring中这些开发技巧真的太diao了
  11. EasyUI后台管理系统
  12. jscpd--前端代码重复率检测
  13. 篮球的各个位置的职能!!!
  14. offer比较:华为云核心网产品线和作业帮 都是开发
  15. python虚拟机:pvm
  16. SAP FICO 付款及清账解析
  17. SM-G9008V Root,google框架安装 设置开发者模式
  18. hdu1151Air Raid poj2594Treasure Exploration题解
  19. 【图像压缩】香农熵和差分进化算法多级图像阈值图像压缩【含Matlab源码 2035期】
  20. 怎么能学会做买卖步骤是什么(想做买卖赚钱应该先从什么做起)

热门文章

  1. IntelJIdea 如何修改控制台字体大小和主题
  2. CA虚拟环境访问控制为虚拟化撑起保护伞
  3. 为什么会有这么多种程序设计语言?
  4. select、bash函数初识及rpm命令详解
  5. ios运行某些工程时屏幕上下出现黑边的解决办法
  6. Linux TCP 性能調優筆記
  7. Python + OpenCV 环境配置
  8. 面试题 01.07. 旋转矩阵
  9. anaconda安装python包_Anaconda:安装或更新 Python 第三方包
  10. Python字符串与列表间的相互转化